파일에서 여러 문자열을 grep'ping합니다(반드시 같은 줄에 있을 필요는 없음).

파일에서 여러 문자열을 grep'ping합니다(반드시 같은 줄에 있을 필요는 없음).

나는 일부 문자열이 포함된 파일을 더 자주 찾는다는 것을 인정합니다.

현재 나는 이렇게 합니다:

grep -rl string1 | xargs grep -l string2 | xargs grep -l string3

이 작업을 수행할 수 있는 도구가 있나요?

이는 또는 grep입니다 .​string1string2string3

grep -rl -e string1 -e string2 -e string3

string1string2and 를 포함하는 파일을 원 string3하지만 반드시 같은 줄에 있을 필요는 없습니다.

grep어쩌면 현대인 중 한 사람( ) ag/ack/rg/sift이 이것을 할 수 있을까요?

답변1

다음과 같이 사용할 수 있습니다 grep.

grep -rzlP '(?s)(?=.*?string1)(?=.*?string2)(?=.*?string3)' .
  • (?s)알려진 "dot-all"은 다음과 같습니다.grep점이 .새 줄 문자와도 일치하도록 허용합니다.\n

  • (?=.*?pattern): 정방향 예측은 .0번 이상 나타나고 *욕심이 없는 모든 문자와 일치하며 그 뒤에 패턴( string1, string2, ...)이 옵니다.

다음과 같은 함수를 만들 수 있습니다(POSIX bash& zsh).

mgrep() { eval grep -rzlP $(printf ''\''(?s)';
          printf '(?=.*?'\''"$%d"'\'')' $(eval echo {1..$#}); printf ''\''') . ; }

그런 다음 다음과 같이 호출하면 현재 작업 디렉터리의 모든 내용이 포함된 파일을 재귀적으로 찾습니다.무늬존재하다.

mgrep string1 string2 string3

grep또한 기본적으로 지원하는 모든 유형의 패턴을 처리합니다 (grep필요에 맞게 기능의 옵션을 미리 조정하세요.).

mgrep string 'pattern with space' '\d+' [0-9]  [...]

답변2

agrep( 원본비슷한grep, )의 것이 아니라 tre할 수 있습니다

agrep -ld '$x' 'pattern1;pattern2;pattern3'

일치할 수 없는 정규식( $x끝 뒤에 오는 것)을 구분 기호로 사용합니다.

( 디렉토리의 모든 파일을 재귀적으로 검색하려면 find또는 재귀 glob을 사용하십시오.)zsh

그러나 패턴은 각 파일의 모든 줄이 아니라 파일의 전체 내용과 일치합니다.

gawk를 사용하여 스크립트를 작성할 수 있습니다.

PATTERNS='pattern1;pattern2;pattern3' gawk -e '
  BEGIN{n = split(ENVIRON["PATTERNS"], a, ";")}
  BEGINFILE{for (i in a) p[a[i]]; found = 0}
  {
    for (i in p)
      if ($0 ~ i) {
        if (++found == n) {print FILENAME; nextfile}
        delete p[i]
      }
  }' -E /dev/null file1 file2...

(느리지만).

답변3

αГsнιn의 답변에 따르면:

mgrep() {
    grep -rzlP "(?s)$(printf "(?=.*?%s)" "$@")" .
}

mgrep string1 string2 string3

답변4

다음 제안은 간단하지만 더 효과적이고 강력할 수 있습니다.

#!/bin/bash

tab=(one three five)

# grep_all's return status indicates if all patterns have at least
# one matching result in the text file specified as argument.

grep_all()
{
    local -n patterns=$1      # allows to refer to an array
    local file=$2

    # abort if a pattern is not found
    for pattern in "${patterns[@]}"; do
        if ! grep -q -e "$pattern" "$file"; then
            return 1
        fi
    done
}

grep_all tab file.txt
echo $?

관련 정보