여러 문자열(둘 중 하나만 포함되지 않고 모두 포함됨)이 포함된 파일을 검색하고 줄 번호를 인쇄합니다.

여러 문자열(둘 중 하나만 포함되지 않고 모두 포함됨)이 포함된 파일을 검색하고 줄 번호를 인쇄합니다.

특정 디렉토리에 있는 파일에서 2개 이상의 문자열을 검색하여 줄 번호를 인쇄하고 싶습니다.

검색결과에는 해당 파일만 포함되어야 합니다.모두언급된 문자열이 존재합니다(같은 줄에 있을 수도 있고 아닐 수도 있음). 모든 문자열이 아닌 일부 문자열을 포함하는 파일을 제외해야 합니다.

이를 달성하기 위해 편리한 명령은 무엇입니까?

답변1

GNU awk를 사용하면 다음을 수행할 수 있습니다.

awk 'BEGINFILE { n1=n2=0 }
     /str1/ { n1=FNR }
     /str2/ { n2=FNR }
     ENDFILE { if (n1&&n2) print FILENAME,n1,n2 }
' files...

고려해야 할 문자열 목록의 변형:

awk -v s="str1 str2 str3" '
  BEGIN { n=split(s,str) ; m=(2^n)-1 }
  BEGINFILE { f=0 }
  { for (i=1; i<=n; i++)
    if ($0 ~ str[i]) {
      l[i] = FNR
      f += 2^(i-1)
    }
  }
  ENDFILE {
    if (f==m)
      for (i=1; i<=n; i++) print FILENAME,l[i]
  }
' files...

이러한 명령은 스크립트 파일에서 가장 잘 실행되며 대체 목록은 매개변수로 스크립트에 전달 files...됩니다 ."$@"

디렉터리(주석에서 요청한 대로)와 검색 문자열을 전달하는 "findall"과 같은 스크립트는 다음과 같습니다.

dir=${1:?}
shift
cd "$dir" || exit 1

awk -v s="$*" '
  ...as above...
' *

라고 할 수 있습니다 findall dir str1 str2 ... strN. (검색 문자열에는 공백 문자가 포함되어서는 안 됩니다.)

답변2

한 가지 방법은 먼저 일치하는 파일을 나열한 다음 파일을 다시 읽어 필요한 줄을 찾는 것입니다. 이 방법은 일치 파일이 너무 크거나 너무 많지 않은 한 잘 작동합니다.

특수 문자가 포함된 파일 이름 문제를 방지할 수 있는 최신 GNU 유틸리티(Linux/Cygwin)가 충분하다고 가정합니다.

grep -Rlz -Fe "foo" . |
xargs -0 grep -lz -Fe "bar" /dev/null |
xargs -0 grep -lz -Fe "qux" /dev/null |
xargs -0 awk '/foo|bar|qux/ {print FNR}' /dev/null

관련 정보