Diese Frage hat hier bereits Antworten :

Kommentare

  • Was meinst du? durch " den gesamten Teil jeder Zeichenfolge "? Sie möchten nicht, dass ' die gesamte Zeile gedruckt wird?
  • Können Sie bestätigen, dass übereinstimmende Dateien beide " foo " und " 321 " aber nicht nur " foo " oder nur " 321 "?
  • Mir gefällt, wie es ' s 321 anstelle von bar ist: – D

Antwort

GNU grep

Sollte etwas schneller sein, da die zweite grep kann eine Liste von Dateien bearbeiten.

grep -lZ "foo" * | xargs -0 grep -l "321" 

POSIX grep mit find

find ist nützlicher, wenn Sie rekursive Verzeichnisse durchsuchen möchten (in diesem Fall verlieren Sie die -mindepth und -maxdepth Optionen.

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q "foo" {} \; -exec grep -l "321" {} + 

Kommentare

  • -r hat beim ersten grep einwandfrei funktioniert, um diese GNU-Lösung für mich rekursiv zu machen. anstatt die POSIX-Zeile mit all diesen exec s

Antwort

zu verwenden

Sie können dies mit einem kurzen Skript tun:

for FILE in * do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE done 

Sie können dies auch in einer Zeile tun:

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done 

grep gibt 0 (true) zurück, wenn der String gefunden wurde, und die &&, die die Befehle trennt, bedeutet dies Der zweite wird nur ausgeführt, wenn der erste wahr war. Die Option -q stellt sicher, dass grep nichts ausgibt.

Das Echo wird nur ausgeführt, wenn beide Zeichenfolgen vorhanden sind gefunden in der gleichen Datei.


Ich dachte über eine andere Art, es zu tun. Diese Methode ist wahrscheinlich effizienter, wenn die betreffenden Dateien größer als Ihr installierter Arbeitsspeicher sind, da sie nur einmal grep durch jede Datei gehen müssen.

 for FILE in * do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE done 

und die einzeilige Version:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done 

Kommentare

  • Für Ihre effizientere Lösung: Was ist, wenn die Datei " foo foo " enthält?
  • That ' ist das, wofür uniq | sort | uniq ist. " foo foo " ist eine Zeile, aber " foo 321 " besteht letztendlich aus zwei Zeilen, da grep -o alle gefundenen Zeichenfolgen in separaten Zeilen ausgibt, auch wenn sie in derselben Zeile begonnen haben.
  • Wenn die Dateien so groß werden, dass es in Ordnung wäre, mindestens sechs Mal pro Datei zu gabeln, ist es wahrscheinlich sinnvoll, stattdessen awk zu verwenden, damit die Dateien nicht bis zum Ende durchsucht werden müssen.
  • @Ladadadada got es. 🙂
  • @HaukeLaging grep -q und grep -l suchen nicht bis zum Ende der Datei: Sie werden sofort beendet als Übereinstimmung gefunden wird. Ich frage mich, warum die erste Lösung nicht ' t for FILE in *; do grep -q foo "$FILE" && grep -l 321 "$FILE"; done

Antwort ist

Seltsam. Für mich funktionieren beide Varianten (grep (GNU grep) 2.13):

grep "foo\|321" grep -E "foo|321" 

Bearbeiten Sie 1 – Nur Dateien mit beiden Übereinstimmungen anzeigen

Die Antwort for file in * funktioniert, kann jedoch zu einem Leistungsalptraum werden (für große Mengen von Dateien) ): mindestens zwei Prozesse pro Datei. Dies ist schneller (in der GNU-Welt):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 | xargs -0 -r grep --files-with-matches -- string2 

string1 sollte derjenige sein, der zu weniger Übereinstimmungen führt.

Kommentare

  • Der Fragesteller sucht nach einem Ergebnis, das nur dann true zurückgibt, wenn eine Datei beide Zeichenfolgen enthält, anstatt nur mindestens einer zu entsprechen.
  • Das gefällt mir --files-with-matches Option. Lesen Sie es einfach in der Manpage nach und es führt dazu, dass grep stoppt, nachdem es die erste Übereinstimmung gefunden hat. Dies bedeutet, dass ' für große Dateien sehr effizient ist, wenn die Übereinstimmung früh auftritt. Es heißt auch, dass die kurze Option -l von POSIX angegeben wird, sodass sie außerhalb der GNU-Welt verwendet werden kann.
  • @Ladadadada Die Effizienz ist kein Vorteil gegenüber Ihrer -q aber. Als ich GNU erwähnte, dachte ich nicht ' an –files-with-match, sondern an -0 / –null.Was mir gerade in den Sinn kommt: Die Pfadnamenerweiterung enthält eine alphabetische Sortierung (wirklich schlecht: Es scheint, dass ' nicht einmal deaktiviert werden kann), sodass für große Mengen von Dateien sogar Ihre for file in * macht wirklich keinen Spaß mehr.
  • In der Tat wären die Effizienzoptimierungen für einige große Dateien ganz anders als für viele kleine und * funktioniert nach einigen tausend Dateien einfach nicht mehr '.
  • @Ladadadada ' funktioniert nicht als Teil einer Befehlszeile für einen externen Befehl: grep foo * Aber for file in * ist eine Shell-interne Struktur, also würde ich annehmen dass das Befehlszeilenlimit hier nicht anwendbar ist.

Antwort

Grundsätzlich, um alle Dateien einschließlich einer bestimmten zu finden Zeichenfolge in einem Verzeichnis können Sie verwenden:

grep -lir "pattern" /path/to/the/dir 
  • -l: um diesen Scan durchzuführen stoppt bei der ersten Übereinstimmung
  • -i: um Groß- und Kleinschreibung sowohl im Muster als auch in den Eingabedateien zu ignorieren
  • -r: Durchsuchen Sie alle Dateien im Verzeichnis rekursiv.

Um nach zwei Mustern zu suchen, versuchen Sie Folgendes:

grep -lr "321" $(grep -lr "foo" /path/to/the/dir) 

Kommentare

  • Langweilige Standardkommentare zu $(), die Leerzeichen nicht gut behandeln, gelten. In der Praxis funktioniert dieser Befehl für einen Liner in der Shell einwandfrei.

Antwort

Sollte

grep -e "foo" -e "321" * 

Verwenden Sie -e für mehrere Muster

BEARBEITEN

Falls beide übereinstimmen müssen:

grep -e ".*foo.*321.*" * 

Wenn die Reihenfolge keine Rolle spielt:

grep -e ".*foo.*321.*" ".*321.*foo.*" * 

Kommentare

  • Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag.
  • @mdpc Ich denke, er liefert eine Antwort. Was lässt Sie anders denken?
  • @HaukeLaging Weil es zurückgibt, wenn eines der Muster übereinstimmt. Das OP sucht nach einem Fall, in dem es nur dann true zurückgibt, wenn beide in der Datei gefunden werden.
  • Nach meinem Verständnis werden nur Dateien gefunden, in denen beide Zeichenfolgen in derselben Zeile enthalten sind (I. ' denke nicht. Entspricht standardmäßig Zeilenumbrüchen)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.