grep, awk 또는 sed를 사용하여 한 패턴과 일치하지만 다른 패턴과 일치하지 않는 파일을 찾으세요.

grep, awk 또는 sed를 사용하여 한 패턴과 일치하지만 다른 패턴과 일치하지 않는 파일을 찾으세요.

하나의 문자열(예:)을 포함하지 않지만 다른 문자열(예:)을 포함하는 파일을 찾아야 합니다 .php..plaaabbb

현재 다음 명령을 사용하고 있습니다.

find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec sh -c 'grep -l -v "aaa" {} | grep -l "bbb" {}' \; > resulttofile

검색할 파일이 50만개 정도 있는데 알고 싶습니다.

  • 내 명령이 올바르게 작동하면 눈 샘플링을 통해 긍정적인 결과를 얻을 수 있습니다.
  • 다른 형식(현재 가상 머신에서는 약 2분 정도 소요되지만 더 많은 파일이 추가될 예정)을 사용하거나 대신 또는 둘을 조합하여 사용하는 것이 더 빠를 awksed있는 경우 grep.grep

시스템은 Debian GNU/Linux입니다.

답변1

귀하의 명령은 작동하지 않습니다. 첫 번째 명령은 grep일치하지 않는 행을 포함하는 모든 파일을 나열하고 "aaa", 두 번째 명령은 처리할 자체 파일을 제공하기 때문에 첫 번째 명령의 출력을 무시합니다. 따라서 여부에 관계없이 grep일치하는 파일 목록을 가져옵니다. "bbb"그것들은 포함되어 있습니다 "aaa". 줄 일치 ( ) grep가 없는 경우에만 파일이 나열되도록 요청 하고 결과 파일 목록을 처리하여 두 번째 파일에만 공급해야 합니다 (또는 두 번째 파일이 첫 번째 파일로 시작하도록 해야 합니다)."aaa"grep -Lxargsgrepgrep

결론은 find나열된 파일 이름이 셸에 문제를 일으키지 않는 경우에만 작동한다는 것입니다. 특히 {}주어진 명령에 직접 포함하면 sh -c파일 이름이 결국 셸 명령으로 해석됩니다(참조"find -exec sh -c"를 사용해도 안전합니까?더 알아보기).

GNU를 사용한다고 가정하면 다음은 더 적은 grep호출이 필요하고 더 안전합니다.grep

find /path/ \( -iname '*.php*' -o -name '*.pl*' \) -exec grep -LZ aaa {} + |
  xargs -r0 grep -l bbb

이것-or연산자는 GNU 확장입니다 find. 사용-o휴대성을 위해.

답변2

테스트되지 않았지만 GNU awk를 사용하여 원하는 대로 작동할 것입니다 nextfile.ENDFILE

find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec awk '
    /aaa/{a=1} /bbb/{b=1} a&&b{nextfile} ENDFILE{if (b && !a) print FILENAME; a=b=0}
' {} + > resulttofile

위의 내용은 여러 파일에 대해 awk를 한 번만 호출하므로 효율적입니다.

위는 일반적으로 파일의 여러 패턴을 일치시킨 다음 파일을 완전히 읽은 후 일치된 조합의 결과를 평가하는 방법이지만 다음과 같습니다.@G-Man이 "모니카 복원"이라고 말합니다.에서 언급된코멘트aaa이 특정한 경우에는 성공 기준이 aaa존재하지 않기 때문에 일치하는 항목에서 현재 파일 읽기를 중지하여 효율성을 향상시킬 수 있습니다.

/aaa/{a=1; nextfile} /bbb/{b=1} ENDFILE{if (b && !a) print FILENAME; a=b=0}

답변3

find 명령을 사용하여 여러 -exec 지시어(또는 다른 지시어)를 연결할 수 있습니다.

find /path \( -iname '*.php*' -or -name '*.pl*' \) -exec grep -q "bbb" {} ";" \
     -exec grep -L "aaa" {} ";" > resulttofile

(줄바꿈은 SE의 레이아웃에 맞추기 위한 것입니다).

관련 정보