Angenommen, ich habe eine patterns.txt
und 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 cat
Befehl 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 grep
viel schneller!
Sie könntenauch verwendencmp
anstelle 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 -q
uns wissenWaswird vermisst.
2a3
> missing_word
Antwort3
mit grep
einer PCRE-Erweiterung und unter Verwendung der printf
Befehlsleistung 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 matched
wird ausgegeben, andernfalls Textone or more pattern(s) does not found
wird widerhallen.
dies verhält sich wie ein übereinstimmendes Muster, z. B. pat[01]
stimmt mit beiden überein pat0
und pat1
; um dem genauen Muster zu entsprechen, pat[01]
ändern Sie wörtlich printf
den Steuermodifikator von in , %s
wodurch %q
Sonderzeichen vermieden werden.
<infile grep -qzP "(?s)$(printf "(?=.*?%q)" $(<pattern.txt))" &&
echo 'all matched' ||
echo 'one or more pattern(s) does not found'