Ich möchte alle Zeilen in mehreren Dateien finden, die einem von zwei Mustern entsprechen. Ich habe versucht, die Muster, nach denen ich suche, durch Tippen zu finden
grep (foo|bar) *.txt
Aber die Shell interpretiert das |
als Pipe und beschwert sich, wenn bar
es sich nicht um eine ausführbare Datei handelt.
Wie kann ich in einem Satz von Dateien nach mehreren Mustern suchen?
Antworten:
Zunächst müssen Sie das Muster vor der Expansion durch die Shell schützen. Der einfachste Weg, dies zu tun, besteht darin, einfache Anführungszeichen zu setzen. Einfache Anführungszeichen verhindern die Erweiterung von Elementen (einschließlich umgekehrter Schrägstriche). Das einzige, was Sie dann nicht tun können, sind einfache Anführungszeichen im Muster.
Wenn Sie ein einfaches Anführungszeichen benötigen, können Sie es als
'\''
(Endzeichenfolgenliteral, Literalzitat, offenes Zeichenfolgenliteral) schreiben .Zweitens unterstützt grep zwei Syntaxen für Muster. Die alte Standardsyntax ( grundlegende reguläre Ausdrücke ) unterstützt den
|
Operator alternation ( ) nicht, obwohl er in einigen Versionen als Erweiterung, jedoch mit einem Backslash geschrieben ist.Der portable Weg ist, die neuere Syntax zu verwenden, erweiterte reguläre Ausdrücke . Sie müssen die
-E
Option übergebengrep
, um es auszuwählen. Unter Linux können Sie auchegrep
anstelle vongrep -E
eingeben (bei anderen Unices können Sie dies als Alias festlegen).Eine andere Möglichkeit, wenn Sie nur nach einem von mehreren Mustern suchen (im Gegensatz zum Erstellen eines komplexen Musters mit Disjunktion), besteht darin, mehrere Muster an zu übergeben
grep
. Sie können dies tun, indem Sie jedem Muster die-e
Option voranstellen .quelle
fgrep
odergrep -F
bei kleinen Mustern wird der Unterschied vernachlässigbar sein, aber wenn sie länger werden, zeigen sich die Vorteile ...grep -F
tatsächlich ein Leistungsvorteil erzielt wird, hängt von der grep-Implementierung ab: Einige von ihnen wenden sowieso denselben Algorithmus an, sodass sich-F
dies nur auf die Zeit auswirkt, die für das Parsen des Musters aufgewendet wird, und nicht auf die Zeit für die Suche. GNU grep ist-F
zum Beispiel mit nicht schneller (es hat auch einen Fehler, dergrep -F
in Multibyte-Gebietsschemata langsamer macht - dasselbe konstante Muster mitgrep
ist tatsächlich bedeutend schneller!). Auf der anderen Seite profitiert BusyBox grep sehr von-F
großen Dateien.egrep
älter istgrep -E
. Es ist nicht GNU-spezifisch (es hat sicherlich nichts mit Linux zu tun). Tatsächlich gibt es immer noch Systeme wie Solaris, bei denen die Standardeinstellunggrep
immer noch nicht unterstützt wird-E
.oder
selektives Zitieren der Manpage von gnu-grep:
(...)
Am Anfang habe ich nicht weiter gelesen, also habe ich die subtilen Unterschiede nicht erkannt:
Ich habe immer egrep und unnötigerweise parens verwendet, weil ich aus Beispielen gelernt habe. Jetzt habe ich etwas Neues gelernt. :)
quelle
Wie TC1 sagte,
-F
scheint die Option verwendbar zu sein:quelle
Erstens müssen Sie Anführungszeichen für Sonderzeichen verwenden. Zweitens
grep
wird der Wechsel trotzdem nicht direkt verstanden; Sie müsstenegrep
oder (nur mit GNUgrep
) verwendengrep -E
.(Die Klammern sind nicht erforderlich, es sei denn, die Abwechslung ist Teil eines größeren regulären Ausdrucks.)
quelle
grep -E
ist mehr Standard alsegrep
.Wenn Sie keine regulären Ausdrücke benötigen, können Sie diese viel schneller
fgrep
odergrep -F
mit mehreren -e-Parametern verwenden:fgrep
(alternativgrep -F
) ist viel schneller als reguläres grep, da nach festen Zeichenfolgen anstatt nach regulären Ausdrücken gesucht wird.quelle
fgrep
hingewiesen wird , dass dies veraltet ist.Sie können den folgenden Befehl verwenden, um das Ergebnis zu erhalten:
quelle
Eine billige und fröhliche Art, nach mehreren Mustern zu suchen:
quelle
-f
Option von grep eine Datei mit mehreren Mustern akzeptiert. Anstatt eine temporäre Datei zu erstellen (die Sie möglicherweise später nicht löschen möchten), verwenden Sie einfach die Prozessersetzung der Shell:grep -f <(echo foo; echo bar) *.txt
Pipe (
|
) ist ein spezielles Shell-Zeichen, daher muss es entweder mit Escape-Zeichen versehen (\|
) oder in Anführungszeichen gesetzt werden (man bash
):Siehe: Welche Zeichen müssen in Bash maskiert werden?
Hier sind einige Beispiele (mit Tools, die noch nicht erwähnt wurden):
Verwenden von
ripgrep
:rg "foo|bar" *.txt
rg -e foo -e bar *.txt
Verwenden von
git grep
:git grep --no-index -e foo --or -e bar
Hinweis: Es werden auch boolesche Ausdrücke wie
--and
,--or
und unterstützt--not
.Informationen zur UND-Verknüpfung pro Zeile finden Sie unter: Ausführen von grep mit mehreren UND-Mustern.
Informationen zur UND-Verknüpfung pro Datei finden Sie unter: So überprüfen Sie, ob in einer Datei mehrere Zeichenfolgen oder reguläre Ausdrücke vorhanden sind.
quelle
Ich hatte Zugriffsprotokolle, in denen die Daten dumm formatiert waren: [30 / Jun / 2013: 08: 00: 45 +0200]
Aber ich musste es anzeigen als: 30.06.2013 08:00:45
Das Problem ist, dass ich mit "OR" in meiner grep-Anweisung die beiden Übereinstimmungsausdrücke in zwei separaten Zeilen erhalten habe.
Hier ist die Lösung:
quelle
TL; DR: Wenn Sie nach dem Abgleichen eines der mehreren Muster weitere Schritte ausführen möchten, fügen Sie diese wie in ein
\(pattern1\|pattern2\)
Beispiel: Ich möchte alle Stellen finden, an denen eine Variable, die den Namen 'Datum' enthält, als String oder int definiert ist. (zB "int cronDate =" oder "String textFormattedDateStamp ="):
Mit
grep -E
brauchen Sie weder die Klammern noch die Pipe zu verlassen, dhgrep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='
quelle
Das funktioniert bei mir
quelle
Hierfür gibt es mehrere Möglichkeiten.
grep 'foo\|bar' *.txt
egrep 'foo|bar' *.txt
find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'
Die 3. und 4. Option greift nur auf die Dateien zu und vermeidet, dass Verzeichnisse
.txt
in ihren Namen enthalten sind.Entsprechend Ihrem Anwendungsfall können Sie also eine der oben genannten Optionen verwenden.
Vielen Dank!!
quelle
Um die Antwort von @geekosaur zu ergänzen, verwenden Sie den folgenden Befehl, wenn Sie mehrere Muster haben, die auch Tabulatoren und Leerzeichen enthalten
Dabei
[[:blank:]]
ist RE eine Zeichenklasse, die entweder ein Leerzeichen oder ein Tabulatorzeichen darstelltquelle