2013-08-23 3 views
3

나는 foobar.txt라는 텍스트 파일을 가지고 있는데, 그 길이는 10KB 정도입니다. 그러나 다음 일치 검색 명령은 고성능 Linux 컴퓨터에서 약 10 초가 걸립니다.왜 배쉬 패턴이 일치합니까? (* [[: class :]]) foobar가 느린 이유는 무엇입니까?

bash>shopt -s extglob 
bash>[[ `cat foobar.txt` == ?(*[[:print:]])foobar ]] 

일치하는 항목 없음 : foobar.txt의 모든 문자가 인쇄 가능하지만 "foobar"문자열이 없습니다.

검색은 두 가지 대안을 일치하도록 시도해야한다, 그들 각각이 일치하지 않습니다

"foobar" 

instantenous의 그

*[[:print:]]foobar 

- 같이 가야하는 것은 어떤 :

는 스캔한다 한 번에 한 문자 씩 문자를 파일화 할 때마다 다음 문자가 있는지 확인하십시오.

[[:print:]]foobar 

또한 속도가 빨라야하며 문자 당 밀리 초가 걸릴 수 없습니다. 내가 떨어 뜨리면?

는 사실, 즉,이

bash>[[ `cat foobar.txt` == *[[:print:]]foobar ]] 

이 순간하다 할 수있다. 그러나 이것은 위의 두 번째 대안인데, 첫 번째 대안은 없다.

왜 그렇게 오래?

+2

그런 것들을 위해 특별한 유틸리티를 사용해야합니다. ''grep'',''sed'' 또는'awk''와 비슷합니다. –

답변

3

다른 사람들이 언급했듯이 grep을 사용하는 것이 더 나을 것입니다. 결합 @konsolebox 및 RICI의 조언 @ - - 당신이 [[ 조건을 고수하기를 원한다면

는 말했다 그것은 당신이 얻을 것 :

[[ $(<foobar.txt) =~ (^|[[:print:]])foobar$ ]] 

편집 : 정규식은 영업 이익의 요구 사항에 일치하도록 업데이트 - 감사합니다 @ 라이시.

일반적 것이 주목적 일치되어, 오히려합니다 (== 연산자를 통해) 패턴을 [로빙]보다 (이 경우, =~ 연산자를 통해) 문자열 정합 정규식 사용하는 것이 바람직 파일 및 폴더 이름.

+0

사실, 당신의 패턴을 보면 나는 내 대답에 올바르게 정규 표현식을 작성하지 않았다는 것을 깨닫게했다. 그러나 당신은 정확하지 않습니다. 그는 전적으로'foobar '로 구성된 문자열이나 인쇄 가능한 문자로 끝나는 문자열을'foobar'에 이어 일치 시키려고합니다. 정규 표현식에서'[[: print :]]? '는 가능한 정규 표현식과 아무런 차이가 없으므로 훌륭한 정규 표현식 최적화 프로그램에 의해 완전히 제거 될 수 있습니다. – rici

+0

감사합니다. 예, 대답은 ==는 Perl과 같은 패턴 매치를하지 않는다는 것입니다. "바보"로 보입니다. 해결 방법은 = ~을 "똑똑하게"사용하는 것입니다. 실제로, = ~을 사용하여 위와 같은 패턴을 만들면 빠릅니다. –

+0

@rici : 좋은 점, 감사합니다. 정규 표현식을 업데이트했습니다. – mklement0

1

bash의 여러 포크 (하나는 서브 쉘, 하나는 cat 명령)를 수행하고 실행하는 동안 cat 바이너리도 읽습니다.

[[ `cat foobar.txt` == *[[:print:]]foobar ]] 

이 양식은 빠른 것 :

[[ $(<foobar.txt) == *[[:print:]]foobar ]] 

아니면 차이를하지 않는 경우 패턴 매칭의 속도가 강타 당신의 버전과 관련이있을 수

IFS= read -r LINE < foobar.txt && [[ $LINE == *[[:print:]]foobar ]] 

다시 사용하고있어.

+0

고맙습니다. 캐릭터 . 그것은 중요합니다. 모든 것이 빠릅니다. 그게 사실 내 포인트 야, 왜 "?" 문제. –

+0

'cat'을 내장 된 것으로 바꾸면 몇 마이크로 초 이상을 절약 할 수 있다고 믿기가 정말 어렵습니다. – rici

+0

@rici 명령 경로와 바이너리가 아직 캐싱되지 않은 경우 IO 속도에 따라 분명히 달라질 수 있습니다. – konsolebox

6

bash의 glob matcher는 최적화되지 않았습니다. 그것은 해석 - 온 - 더 - 플라이 정규의,

그것은 정규 표현식 엔진이 아니다 : bash는 테이너 쳇 레이미 말하는 동안, 예를 들어, this bug-bash thread를 들어, 참조하십시오.

bash는이뿐만 아니라 정규 표현식 엔진이 포함되어 있기 때문에이 ([[ ]] 내부 =~ 대신 == 사용), 아마 그것에 대해 아무것도 할 많은 동기 부여가 아니다.

내 컴퓨터에서 동등한 정규 표현식 (^(.*[[:print:]])?foobar$)은 로케일 인식 [[:print:]]; 웬일인지, 그것은 glob 일치 자에 영향을 미치지 않았습니다. LANG = C로 설정하면 정규 표현식이 잘 작동합니다.

그러나 그 크기의 문자열의 경우 grep을 사용합니다.

관련 문제