Grep-Dateien mit Muster A, aber schließen Sie Dateien mit Muster B aus

Grep-Dateien mit Muster A, aber schließen Sie Dateien mit Muster B aus

Ich möchte nach Dateien greppen, die Muster A enthalten (ich will), aber Dateien ausschließen, die Muster B enthalten (ich will nicht).

Beispiel:

read -p "...what are you looking for: " iwant
read -p "...what should not be included: " idontwant

iwant="blue car" 
idontwant="red car"

Nehmen wir einfach an, ich habe die folgenden Dateien:

-rw-rw-r--.  1 terpentin terpentin  45 Jun  8 16:04 blue.car
-rw-rw-r--.  1 terpentin terpentin  44 Jun  8 16:05 mixed.car
-rw-rw-r--.  1 terpentin terpentin  40 Jun  8 16:04 red.car
find . -type f -print -exec cat {} \;

./mixed.car
blue car
red car
blue car

./red.car
red car
red car
red car

./blue.car
blue car
blue car
blue car

Wie ist es möglich, als Ergebnis nur die Datei „./blue.car“ zu erhalten?

Der Originalinhalt umfasst Hunderte langer Textdateien, weshalb es wichtig ist, so ressourcenschonend wie möglich zu sein.

Antwort1

Verwenden

find . -type f ! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -print

oder

find . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -print
  • Die Begriffe (manchmal auch „Prädikate“ genannt) in einem find Befehl werden charakterisiert alsTests(zB  -type f) undAktionen(z. B.  -printund  -delete). Aus der Manpage kann man schwer erkennen, dass -execes sich sowohl um ein Aktionund ein prüfen. So, genau wie
    suchen . -Typ f -mtime -30 -name '*.txt' -lesbar -size +5Prüfung 6 Prüfung 7 Prüfung 8
    schränkt die Suche sukzessive auf Dateien ein, die alle Kriterien erfüllen (alle angegebenen Tests bestehen), so
    finden . -execBefehl 1{} ';' -execBefehl 2{} ';' -execBefehl 3{} ';' …
    findet Dateien, für die alle Befehle erfolgreich sind.
  • Jeder findTest kann negiert (invertiert) werden, indem man ihm ein voranstellt !. So find . ! -type dwerden einfache Dateien, symbolische Links, benannte Pipes, Sockets und Gerätedateien gefunden – alles außer Verzeichnissen.
  • Beachten Sie, dass dies ! -exec grep …nicht gleichbedeutend ist mit -exec grep -v …-exec grep -v …findet Dateien, die mindestens eine Zeile enthalten, die nicht übereinstimmt.  ! -exec grep …findet Dateien, bei denenNEINZeilen stimmen überein.
  • Die -qOption zu grepist offiziell ein Synonym für --quiet, bedeutet aber auchschnell. Es wird keine Ausgabe ausgegeben (außer eventuellen Fehlermeldungen), aber es wird beendet, sobald es eine Übereinstimmung findet – es liest nicht jede Datei bis zum Ende, um zu findenjedenÜbereinstimmung. (Wenn eine Datei keine Übereinstimmungen enthält, muss sie natürlich grepvollständig gelesen werden, um dies festzustellen.)
  • Also (Kurz zusammengefasst) finden die Befehle die Dateien, für die
    grep -q "$ichwill"     Datei
    gelingt und
    grep -q "$willnicht"Datei
    schlägt fehl (weil wir es mit vorangestellt haben !).
  • Die beiden Befehle sind funktional gleichwertig, können aber eine unterschiedliche Leistung aufweisen (d. h. die Ausführung kann unterschiedlich lange dauern). Wenn nur wenige Dateien die Suchzeichenfolgen enthalten,
    finden . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' –print
    ist schneller, da dadurch grep "$iwant"die meisten Dateien eliminiert werden. Wenn viele der Dateien beide Zeichenfolgen enthalten, dann
    finden . -type f ! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' –print
    wird schneller sein, weil dadurch ! grep "$idontwant"die meisten Dateien gelöscht werden.

Antwort2

Mit GNU grepkönnen wir die Dateinamenextraktion mit einer umsichtigen Auswahl von Regex- und Grep-Optionen durchführen:

$ grep -lzPsr '(?s:(?=.*blue)(?!.*red))' .

Wir betreiben grep im Slurp-Modus (-z), wobei die gesamte Datei als eine große Zeile behandelt wird.

Mit -l werden die Dateinamen der Dateien aufgelistet, die dem regulären Ausdruck entsprechen.

Die Option -r wird rekursiv auf allen Dateien im aktuellen Verzeichnis und darunter ausgeführt.

Mit -s wird grep stummgeschaltet, sodass keine Warnungen ausgegeben werden.

Der reguläre Ausdruck sucht in einer Datei nach dem Vorhandensein von Blau und dem Fehlen von Rot, um eine Antwort „Ja“ zu geben.

Mit -P wird die Perl-Regex-Engine in grep aufgerufen, sodass wir die Vorteile von pcre-Regexen nutzen können.

verwandte Informationen