Überprüfen Sie, ob alle Muster in der Datei sind

Überprüfen Sie, ob alle Muster in der Datei sind

Angenommen, ich habe eine patterns.txtund möchte überprüfen, ob jedes dieser Muster in einer Datei vorhanden ist.

Ich könnte so etwas tun wie:

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"

Dies ist jedoch ineffizient, da für jedes Muster erneut gescannt werden muss file.txt(und es ist nicht so einfach, wenn wir statt in einer Datei nach Mustern in einem Stream suchen, der beispielsweise aus einer möglicherweise großen Pipe kommt).

Gibt es eine Möglichkeit grep(oder ein anderes Tool), zu überprüfen, oballedie Muster sind vorhanden?

Antwort1

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 -

Ersetzen Sie den catBefehl durch eine beliebige Pipeline, die Text erzeugt.

Antwort2

Das könnte gut funktionieren:

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

Wenn Sie feste Zeichenfolgen anstelle von Mustern haben, verwenden Sie -F. Das geht grepviel schneller!

Sie könntenauch verwendencmpanstelle von diff -s. Das ist zwar etwas schneller, kann aber nicht zeigen, was fehlt.


Ausgabe wenn nicht alle Muster gefunden wurden:

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

oder wenn alle Muster gefunden wurden:

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

Lassen Sie es -quns wissenWaswird vermisst.

2a3
> missing_word

Antwort3

mit grepeiner PCRE-Erweiterung und unter Verwendung der printfBefehlsleistung würden Sie etwa Folgendes tun:

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

wenn alle Muster (injede Bestellung) in der Eingabedatei gefundenim Ordnerdann Textall matchedwird ausgegeben, andernfalls Textone or more pattern(s) does not foundwird widerhallen.

dies verhält sich wie ein übereinstimmendes Muster, z. B. pat[01]stimmt mit beiden überein pat0und pat1; um dem genauen Muster zu entsprechen, pat[01]ändern Sie wörtlich printfden Steuermodifikator von in , %swodurch %qSonderzeichen vermieden werden.

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

verwandte Informationen