Drucken Sie unvergleichliche Muster mit grep und Mustern aus der Datei


14

patterns.txt:

"BananaOpinion"
"ExitWarning"
"SomeMessage"
"Help"
"Introduction"
"MessageToUser"

Strings.xml

<string name="Introduction">One day there was an apple that went to the market.</string>
<string name="BananaOpinion">Bananas are great!</string>
<string name="MessageToUser">We would like to give you apples, bananas and tomatoes.</string>

Erwartete Ausgabe:

"ExitWarning"
"SomeMessage"
"Help" 

Wie drucke ich die Begriffe aus, in patterns.txtdenen sich nichts befindet Strings.xml? Ich kann die abgestimmt / unerreichten Drucklinien in Strings.xml, aber wie drucke ich die unerreichten Muster ? Ich benutze ggrep (GNU grep) Version 2.21, bin aber offen für andere Tools. Entschuldigung, wenn dies ein Duplikat einer anderen Frage ist, die ich nicht finden konnte.

Antworten:


24

Sie können grep -onur das passende Teil drucken und das Ergebnis für eine Sekunde als Muster für grep -vdie Originaldatei patterns.txtverwenden:

grep -oFf patterns.txt Strings.xml | grep -vFf - patterns.txt

In diesem speziellen Fall können Sie jedoch auch join+ verwenden sort:

join -t\" -v1 -j2 -o 1.1 1.2 1.3 <(sort -t\" -k2 patterns.txt) <(sort -t\" -k2 strings.xml)

das ist ganz elegant .. schlau!
XXL

Wenn Sie mehrere Eingabedateien haben (z. B. Strings1.xmlund Strings2.xml), benötigen Sie auch das -hFlag auf dem ersten Grep.
Jayhendren

@ Jayhendren - ja, aber nicht alle grepunterstützen diese Option. Wenn Sie mehrere Eingabedateien haben, verstehe ich nicht, warum Sie sie nicht catalle haben können und leiten Sie das Ergebnis an grep.
don_crissti

5

Der beste Ansatz ist wahrscheinlich der, den @don_crissti vorgeschlagen hat. Hier ist eine Variation desselben Themas:

$ grep -vf <(grep -Po 'name=\K.+?"' Strings.xml) patterns.txt
"ExitWarning"
"SomeMessage"
"Help"

Dies ist im Grunde das Gegenteil von @ don_crisstis Ansatz. Es verwendet grep mit Perl-kompatiblen regulären Ausdrücken ( -P) und dem -oSchalter, um nur den passenden Teil der Zeile zu drucken. Dann sucht name=und verwirft der Regex ( \K) und sucht dann nach einem oder mehreren Zeichen bis zum ersten "( .+?"). Dies ergibt die Liste der in der String.txtDatei vorhandenen Muster, die dann als Eingabe an ein umgekehrtes grep ( grep -v) unter Verwendung von process substitution ( <(command)) übergeben werden.


2

Ich würde cutwahrscheinlich verwenden. Das heißt, wenn Sie, wie es scheint, wissen, wo Sie die angeführte Zeichenfolge erwarten können, nach der Sie suchen.

Wenn ich mache:

{   cut  -sd\" -f2 |
    grep -vFf- pat
}   <<\IN
#   <string name="Introduction">One day there was an apple that went to the market.</string>
#   <string name="BananaOpinion">Bananas are great!</string>
#   <string name="MessageToUser">We would like to give you apples, bananas and tomatoes.</string>
IN

... nachdem ich meine eigene Kopie Ihres Beispiels patterns.txtin patgespeichert und den obigen Befehl ausgeführt habe, lautet die Ausgabe:

"ExitWarning"
"SomeMessage"
"Help"

cutDrucke auf stdout nur die zweite "doppelte Anführungszeichen -delimited -field für jeden Begrenzer abgestimmte Eingabezeile und -suppresses alle anderen.

Was cuttatsächlich gedruckt wird, grepist:

Introduction
BananaOpinion
MessageToUser

grepsucht seine benannte Datei - Operanden für Linien , die -vdie nicht übereinstimmen -Fixed Strings in seine -stdin Muster -file.

Wenn Sie sich darauf verlassen können, dass das "zweitbegrenzte Feld übereinstimmt, dann ist dies definitiv eine Optimierung gegenüber dem grep -PErl-Modus, indem Sie nur -Ffestgelegte Zeichenfolgen und nur winzige Teile davon zusammenfügen, da cutdies das schwere Heben bewirkt - und es geht schnell .


1
for p in $(cat patterns.txt); do if ! grep $p strings.xml &>/dev/null; then echo $p; fi; done

Es ist leicht zu verstehen, hat aber die Ausfallzeit, mehrere grep-Prozesse zu erzeugen, einen für jede Zeile in patterns.txt.


0

Eine andere Möglichkeit besteht darin, patterns.txt und Strings.xml in eine Liste aufzunehmen und nach eindeutigen Zeilen zu suchen

cat patterns.txt Strings.xml | grep -oFf patterns.txt | sort | uniq -u

Erläuterung:

cat patterns.txt Strings.xmlfasst alles in einer Liste zusammen. grep -oFf patterns.txtEntfernt den Müll in jeder Zeile. sortselbsterklärend. sortiere alle Zeilen. uniq -udruckt nur einzelne Zeilen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.