모든 패턴이 파일에 있는지 확인

모든 패턴이 파일에 있는지 확인

내가 가지고 있다고 해봐patterns.txt 해당 패턴이 모두 일부 파일에 있는지 확인하고 싶다고 가정해 보겠습니다.

나는 다음과 같이 할 수 있습니다 :

for pattern in $(cat patterns.txt); do 
  if ! grep -q "$pattern" file.txt; then
    echo "Error: missing pattern $pattern"
  fi
done
echo "All patterns found"

하지만 이는 다시 스캔해야 하므로 비효율적입니다.file.txt (예를 들어 파일 대신 파이프에서 나오는 스트림의 패턴을 찾는 경우에는 그렇게 간단하지 않습니다).

grep(또는 다른 도구) 확인 하는 방법이 있습니까 ?모두패턴이 존재하나요?

답변1

cat file.txt | awk '
    NR == FNR {seen[$0] = 0; next} 
    {for (p in seen) if ($0 ~ p) seen[p]++} 
    END {
        for (p in seen) 
            if (seen[p] == 0) {
                missing++
                print "missing pattern", p
            } 
        if (missing == 0) print "all found"
        exit missing
    }
' patterns.txt -

cat명령을 텍스트를 생성하는 파이프라인으로 바꿉니다 .

답변2

이것은 잘 작동할 수 있습니다:

sort -u patterns.txt > sorted_patterns.txt # only once
diff -sq <(grep -o -f sorted_patterns.txt file.txt | sort -u) sorted_patterns.txt

패턴 대신 고정 문자열이 있는 경우 -F. 이렇게 하면 grep속도가 훨씬 빨라 집니다 !

당신은 할 수또한 사용cmp대신에 diff -s. 조금 더 빠를 수도 있지만 누락된 내용을 표시할 수는 없습니다.


모든 패턴이 발견되지 않은 경우 출력:

Files /dev/fd/63 and /dev/fd/62 differ

또는 모든 패턴이 발견된 경우:

Files /dev/fd/63 and /dev/fd/62 are identical

나가다-q알고무엇누락.

2a3
> missing_word

답변3

grepPCRE 확장을 사용 하고 printf명령의 기능도 사용합니다. 당신은 다음과 같은 일을 할 것입니다 :

<infile grep -qzP "(?s)$(printf "(?=.*?%s)" $(<pattern.txt))" &&
 echo 'all matched' ||
 echo 'one or more pattern(s) does not found'

모든 패턴(in어떤 주문이든)가 입력 파일에 있습니다.infile그 다음 문자all matched출력으로 이동합니다. 그렇지 않으면 문자one or more pattern(s) does not found에코됩니다.

이것은 & pat[01]와 일치하는 것처럼 패턴을 일치하는 패턴으로 작동합니다 . 정확한 패턴과 일치하려면 문자 그대로 특수 문자를 이스케이프할 컨트롤 수정자를 변경해야 합니다 .pat0pat1pat[01]printf%s%q

<infile grep -qzP "(?s)$(printf "(?=.*?%q)" $(<pattern.txt))" &&
 echo 'all matched' ||
 echo 'one or more pattern(s) does not found'

관련 정보