Ich suche nach einer Möglichkeit, Dateien zu durchsuchen, in denen zwei Wortinstanzen in derselben Datei vorhanden sind. Bis zu diesem Punkt habe ich Folgendes verwendet, um meine Suchen durchzuführen:
find . -exec grep -l "FIND ME" {} ;
Das Problem, auf das ich stoße, ist, dass das Suchergebnis die Datei nicht liefert, wenn nicht genau ein Leerzeichen zwischen „FIND“ und „ME“ vorhanden ist. Wie passe ich die frühere Suchzeichenfolge an, bei der beide Wörter „FIND“ und „ME“ in einer Datei vorhanden sind, im Gegensatz zu „FIND ME“?
Ich verwende AIX.
Akzeptierte Antwort:
Mit GNU-Tools:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
Sie können standardmäßig Folgendes tun:
find . -type f -exec grep -q FIND {} ; -exec grep -l ME {} ;
Aber das würde bis zu zwei grep
dauern s pro Datei. Um zu vermeiden, dass so viele grep
ausgeführt werden s und immer noch portabel sein, während immer noch alle Zeichen in Dateinamen erlaubt sind, könnten Sie Folgendes tun:
convert_to_xargs() {
sed "s/[[:blank:]"']/\\&/g" | awk '
{
if (NR > 1) {
printf "%s", line
if (!index($0, "//")) printf "\"
print ""
}
line = $0
}'
END { print line }'
}
export LC_ALL=C
find .//. -type f |
convert_to_xargs |
xargs grep -l FIND |
convert_to_xargs |
xargs grep -l ME
Die Idee war, die Ausgabe von find
umzuwandeln in ein für xargs geeignetes Format (das ein Leerzeichen erwartet (SPC/TAB/NL im C
Gebietsschema, YMMV in anderen Gebietsschemas) getrennte Liste von Wörtern, in denen einfache, doppelte Anführungszeichen und umgekehrte Schrägstriche Leerzeichen und einander maskieren können).
Im Allgemeinen können Sie die Ausgabe von find -print
nicht nachbearbeiten , weil es die Dateinamen mit einem Zeilenumbruchzeichen trennt und die Zeilenumbruchzeichen, die in Dateinamen vorkommen, nicht maskiert. Zum Beispiel, wenn wir sehen:
./a
./b
Wir haben keine Möglichkeit herauszufinden, ob es sich um eine Datei namens b
handelt in einem Verzeichnis namens a<NL>.
oder wenn es die beiden Dateien a
sind und b
im aktuellen Verzeichnis.
Durch die Verwendung von .//.
, weil //
kann nicht anders in einem Dateipfad als Ausgabe von find
erscheinen (weil es kein Verzeichnis mit leerem Namen und /
gibt in einem Dateinamen nicht erlaubt ist), wissen wir das, wenn wir eine Zeile sehen, die //
enthält , dann ist das die erste Zeile eines neuen Dateinamens. Also können wir dieses awk
verwenden Befehl, um alle Zeilenumbruchzeichen zu maskieren, außer denen, die diesen Zeilen vorangehen.
Nehmen wir das obige Beispiel, find
würde im ersten Fall (eine Datei) ausgeben:
.//a
./b
Welches awk entkommt zu:
.//a
./b
Damit xargs
sieht darin ein Argument. Und im zweiten Fall (zwei Dateien):
.//a
.//b
Welcher awk
würde so bleiben wie es ist, also xargs
sieht zwei Argumente.
Sie benötigen den LC_ALL=C
also sed
, awk
(und einige Implementierungen von xargs
) funktionieren für beliebige Folgen von Bytes (auch wenn diese keine gültigen Zeichen in der Ländereinstellung des Benutzers bilden), um das Leerzeichen zu vereinfachen Definition auf nur SPC und TAB und um Probleme mit unterschiedlichen Interpretationen von Zeichen zu vermeiden, deren Codierung die Codierung des Backslash durch die verschiedenen Dienstprogramme enthält.