grep을 사용하여 파일에서 여러 문자열을 검색하는 방법(교차점 검색)

grep을 사용하여 파일에서 여러 문자열을 검색하는 방법(교차점 검색)

grep을 사용하여 중첩된 디렉터리 구조에서 다음을 포함하는 파일을 검색하는 방법모두내 검색 패턴에 포함된 단어는 무엇입니까?

여러 단어가 포함된 파일을 찾기 위해 grep을 사용하고 싶습니다. foo bar와 bah를 사용해 보겠습니다. 할 수 있지만 grep -rl foo |xargs grep -rl bah| ...etc더 쉬운 방법이 있나요? 검색할 문자열 파일로 -F를 사용할 수 있다는 것을 알고 있지만 여전히 OR 연산자(합집합)를 사용하여 문자열을 검색하고 AND 연산자(교차)를 사용해야 한다고 생각합니다.

답변1

find+awk해결책:

find . -type f -exec awk '/\<foo\>/{ p1=1 }/\<bar\>/{ p2=1 }/\<bah\>/{ p3=1 }
                          p1 && p2 && p3{ print FILENAME; exit }' {} +

awk프로그램 세부정보:

  • /\<foo\>/{ p1=1 }/\<bar\>/{ p2=1 }/\<bah\>/{ p3=1 }- 각각의 필수 패턴이 발견되면 해당 플래그를 설정합니다.
  • p1 && p2 && p3- 모든 패턴이 발견되면:
    • print FILENAME- 현재 인쇄파일 이름/파일 경로
    • exit- 스크립트 실행 즉시 종료

답변2

내 대답은 @RomanPerekhrest의 답변과 유사합니다. 주요 차이점은 레코드 구분 기호( )를 입력의 어떤 항목과도 ​​일치하지 않는 항목(예:)으로 설정하여 awk전체 입력을 한 번에 처리 할 수 있다는 사실을 활용한다는 것입니다. 즉, 전체 파일을 삼켜 마치 하나의 문자열인 것처럼 검색합니다.RS^$

예를 들어

find . -type f -exec \
  awk -v RS='^$' '/foo/ && /bar/ && /baz/ { print FILENAME }' {} +

.현재 디렉터리( )에 포함된 모든 파일이 나열됩니다 .모두정규식 foo, barbaz. 정규식 중 일부 또는 전부를 전체 단어로 처리해야 하는 경우 단어 경계 앵커로 묶습니다 \<( \>예: ) \<foo\>.

또한 각 파일을 한 번 포크하지 않기 때문에 더 빠르게 실행됩니다 awk. 대신 awk명령줄 버퍼에 맞는 만큼 많은 파일 이름 인수를 사용하여 실행됩니다(최신 시스템에서는 일반적으로 128K 또는 1 또는 2M 문자).... 예를 들어, find1000개의 파일이 발견 되면 awk한 번만 실행되고 1000번은 실행되지 않습니다. .

노트:이를 위해서는 정규 표현식이 awk허용되는 버전이 필요합니다. RS바라보다awk의 후루룩 모드?다른 버전의 awk에서 제한된 형태의 "slurp 모드"를 구현하는 방법에 대한 자세한 내용과 예를 보려면 계속 읽어보세요.

또한 참고하십시오:그러면 메모리에 있는 각 파일의 전체 내용을 한 번에 하나씩 읽습니다. 수십 기가바이트 이상의 로그 파일과 같은 매우 큰 파일의 경우 사용 가능한 RAM 또는 RAM+SWAP을 초과할 수 있습니다. 이런 일이 일어날 가능성은 거의 없지만 만약 발생한다면 심각한 문제가 발생할 수 있습니다(예를 들어 Linux에서 RAM과 SWAP가 부족하면 커널이 무작위 프로세스를 종료하기 시작합니다).

답변3

이와 같은 논리적 AND의 경우 일반적으로 다음을 사용합니다 awk.

awk '/foo/ && /bar/ && /bah/ { print }' /path/to/file

답변4

grep다음과 함께 GNU를 사용하세요-P (펄 호환성)옵션과긍정적인 예측 정규식(?=(regex))한 줄이나 전체 파일에서 순서에 관계없이 단어를 찾고, 현재 디렉터리에서 시작하는 모든 파일에서 반복적으로 단어를 찾습니다.

grep -rlP '(?s)(?=.*?\bfoo\b)(?=.*?\bbar\b)(?=.*?\bbah\b)' .
  • (?s)이것은 DOTALL 수정자이며 다음을 허용합니다.가리키다\newlines를 일치시키기 위해 (.|\n)*?Too 및 betweenwords를 사용합니다 [\s\S]*?.

  • at \bWORD\b; \b은 단어 경계 앵커 포인트입니다.

다음을 입력:

==> file1 <==
foo here and bar
bah
and of file1

==> file2 <==
foo then bar and bah

==> file3 <==
foo foobarbah ba

==> file4 <==
this is foo bar bahh
bah

출력은 다음과 같습니다

./file1
./file2
./sub-dir/file4

관련 정보