Verwenden Sie das Sternzeichen in grep

87

Ich versuche, in einer bestimmten Datei in Linux / Bash nach dem Teilstring "abc" zu suchen

So ich mache:

grep '*abc*' myFile

Es gibt nichts zurück.

Aber wenn ich es mache:

grep 'abc' myFile

Es werden Übereinstimmungen korrekt zurückgegeben.

Das ist für mich kein Problem. Aber was ist, wenn ich nach einer komplexeren Zeichenfolge suchen möchte?

*abc * def *

Wie würde ich es mit grep erreichen?

Saobi
quelle
3
grep selbst unterstützt auf den meisten Plattformen keine Platzhalter. Sie müssen egrep verwenden, um Platzhalter zu verwenden. Shells haben eine andere Syntax. "*" in der Shell ist <jede Zeichenfolge>. In egrep ist es ein Operator, der "0 zu vielen der vorherigen Entität" sagt. In grep ist es nur ein normaler Charakter.
PanCrit
@PanCrit: *bedeutet dasselbe in grep und egrep: Es ist ein Quantifizierer , der null oder mehr des vorhergehenden Atoms bedeutet. Das ist ein völlig anderes Konzept als die von der Shell verwendeten Platzhalter .
Alan Moore

Antworten:

123

Das Sternchen ist nur ein Wiederholungsoperator , aber Sie müssen ihm mitteilen, was Sie wiederholen. /*abc*/Entspricht einer Zeichenfolge, die ab und null oder mehr c enthält (weil das zweite * auf dem c steht; das erste ist bedeutungslos, weil es nichts zu wiederholen gibt). Wenn Sie etwas übereinstimmen möchten, müssen Sie sagen .*- der Punkt bedeutet ein beliebiges Zeichen ( innerhalb bestimmter Richtlinien ). Wenn Sie nur mit abc übereinstimmen möchten, können Sie einfach sagen grep 'abc' myFile. Für Ihre komplexere Übereinstimmung müssen Sie verwenden .*- grep 'abc.*def' myFilewird eine Zeichenfolge abgleichen, die abc gefolgt von def mit etwas optional dazwischen enthält.

Update basierend auf einem Kommentar:

*in einem regulären Ausdruck ist nicht genau das gleiche wie * in der Konsole. In der Konsole ist * Teil eines Glob-Konstrukts und fungiert lediglich als Platzhalter ( ls *.loglistet beispielsweise alle Dateien auf, die mit .log enden). In regulären Ausdrücken ist * jedoch ein Modifikator, was bedeutet, dass er nur für das Zeichen oder die Gruppe davor gilt. Wenn Sie möchten, dass * in regulären Ausdrücken als Platzhalter fungiert, müssen Sie .*wie zuvor erwähnt verwenden - der Punkt ist ein Platzhalterzeichen, und der Stern bedeutet beim Ändern des Punkts, einen oder mehrere Punkte zu finden. dh. Finde einen oder mehrere Charaktere.

Daniel Vandersluis
quelle
1
Ich denke, der Fragesteller ist verwirrt über den Unterschied zwischen Shell-Platzhaltern und regulären Ausdrücken. Ich vermute auch, dass der kompliziertere Ausdruck wäre: grep 'abc. * Def' (mindestens ein Leerzeichen vorhanden - möglicherweise zwei, wie ich geschrieben habe).
Jonathan Leffler
1
Eigentlich scheint der Fragesteller nicht zu verstehen, dass 'abc' nicht dasselbe ist wie '^ abc $' :-D
Massa
1
Ja, ich war verwirrt zwischen glob und vollständigen regulären Ausdrücken. Ich benutze das * ohne Punkt, um zu bedeuten, dass etwas auf der Shell übereinstimmt.
Saobi
1
grep *bedeutet "0 oder mehr" und grep ist standardmäßig gierig. Beachten Sie, dass in grep Grund regulären Ausdrücken die Metazeichen ?, +, {, |, (, und )ihre besondere Bedeutung verlieren. Weitere Informationen: grep regexps
KrisWebDev
24

Das Punktzeichen bedeutet Übereinstimmung mit einem beliebigen Zeichen, .*dh null oder mehr Vorkommen eines beliebigen Zeichens. Sie wollen wahrscheinlich .*eher als nur verwenden *.

smcameron
quelle
Punkt ist ein Metazeichen, das alle Zeichen außer neuen Zeilen akzeptiert .
Abhishek Kamal
12

Das "Sternzeichen" ist nur dann sinnvoll, wenn sich etwas davor befindet. Wenn das Tool nicht vorhanden ist (in diesem Fall grep), wird es möglicherweise nur als Fehler behandelt. Zum Beispiel:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz
Jonathan Leffler
quelle
5
Das * ist nicht bedeutungslos; es hat einfach nicht die übliche Bedeutung (der Wiederholung), sondern bedeutet "Ich bin ein Star". Es würde mit einer Linie übereinstimmen, die einen Stern gefolgt von x, y und z enthält.
Jonathan Leffler
2
@ Jonathan Es kommt auf das Werkzeug an.
7

Verwenden Sie grep -P -, das die Unterstützung von regulären Ausdrücken im Perl-Stil ermöglicht.

grep -P "abc.*def" myfile
Artem Russakovskii
quelle
6

Der Ausdruck, den Sie ausprobiert haben, wie er beispielsweise in der Shell-Befehlszeile unter Linux funktioniert, wird als " glob " bezeichnet. Glob-Ausdrücke sind keine vollständigen regulären Ausdrücke . Daher gibt grep Zeichenfolgen an, nach denen gesucht werden soll. Hier ist ein (alter, kleiner) Beitrag über die Unterschiede. Die Glob-Ausdrücke (wie in "ls *") werden von der Shell selbst interpretiert.

Es ist möglich, von Globs in REs zu übersetzen, aber Sie müssen dies normalerweise in Ihrem Kopf tun.

entspannen
quelle
1
Es ist nur ein Glob, wenn es von der Shell analysiert wird. Da er die Suchzeichenfolge in einfachen Anführungszeichen beibehält, lässt die Shell die Zeichenfolge in Ruhe und übergibt sie intakt in argv an grep.
Auffälliger Compiler
4

Sie verwenden keine regulären Ausdrücke, daher sollte Ihre Grep-Variante der Wahl sein fgrep, die sich so verhält, wie Sie es erwarten.

Andrew Beals
quelle
2
fgrepist jetzt veraltet, grep -fsollte stattdessen verwendet werden.
Prometheus
1
Das ist "grep -F". Der gute alte Fgrep mag "veraltet" sein, aber sie werden es nicht wegnehmen, solange ich noch am Leben bin.
Andrew Beals
3

Versuchen Sie grep -E für eine erweiterte Unterstützung für reguläre Ausdrücke

Schauen Sie sich auch an:

Die grep-Manpage

Brian
quelle
1

Dies könnte die Antwort sein, nach der Sie suchen:

grep abc MyFile | grep def

Das einzige ist ... es werden Zeilen ausgegeben, in denen "def" vor ODER nach "abc" steht.

Charles Duke
quelle
1

Das hat bei mir funktioniert:

grep ". * $ {expr}" - mit doppelten Anführungszeichen, denen der Punkt vorangestellt ist. Wobei "Ausdruck" die Zeichenfolge ist, die Sie am Ende der Zeile benötigen.

Standard Unix Grep ohne zusätzliche Schalter.

Zugriff gewährt
quelle
0

'*' fungiert als Modifikator für das vorherige Element. Also sucht 'abc * def' nach 'ab', gefolgt von 0 oder mehr 'c' gefolgt von 'def'.

Was Sie wahrscheinlich wollen, ist 'abc. * Def', das nach 'abc' sucht, gefolgt von einer beliebigen Anzahl von Zeichen, gefolgt von 'def'.

Auffälliger Compiler
quelle