Wie kann ich für dieses oder jenes (2 Dinge) in einer Datei grep?

37

Ich habe eine Datei, die "dann" und "da" hat.

ich kann

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

und ich kann

$ grep "there " x.x
If there is no blob none some will be created

Wie kann ich in einem Vorgang nach beiden suchen? Ich habe es versucht

$ grep (then|there) x.x

-bash: Syntaxfehler in der Nähe des unerwarteten Tokens `('

und

grep "(then|there)" x.x
durrantm.../code
# (Nothing)
Michael Durrant
quelle

Antworten:

53

Sie müssen den Ausdruck in Anführungszeichen setzen. Der Fehler, den Sie erhalten, ist das Ergebnis einer Bash-Interpretation des (Zeichens als Sonderzeichen.

Außerdem müssen Sie grep anweisen, erweiterte reguläre Ausdrücke zu verwenden.

$ grep -E '(then|there)' x.x

Ohne erweiterte reguläre Ausdrücke, müssen Sie die entkommen |, (und ). Beachten Sie, dass wir hier einfache Anführungszeichen verwenden. Bash behandelt Backslashes in doppelten Anführungszeichen.

$ grep '\(then\|there\)' x.x

Die Gruppierung ist in diesem Fall nicht erforderlich.

$ grep 'then\|there' x.x

Es wäre für so etwas notwendig:

$ grep 'the\(n\|re\)' x.x

quelle
3
Siehe auch grep $'then\nthere'und grep -e then -e there. Beachten Sie, dass \|dies in BREs nicht Standard ist. Der Rest ist. Bash behandelt Schrägstriche speziell in doppelten Anführungszeichen nur vor ", $, \ , `und Newline.
Stéphane Chazelas
1
Was ist der Zweck von x.x?
alex
7

Nur ein kurzer Zusatz, die meisten Aromen haben einen Befehl namens egrep, der nur mit -E grep ist. Ich persönlich mag es viel besser zu tippen

egrep "i(Pod|Pad|Phone)" access.log

Dann grep -E verwenden

Trausti Thor
quelle
2

Das Material, das unter REGELMÄSSIGE AUSDRÜCKE in der (oder zumindest meiner) Manpage dokumentiert ist, ist eigentlich für erweiterte reguläre Ausdrücke gedacht.

grep versteht drei verschiedene Versionen der regulären Ausdruckssyntax: "basic", "extended" und "perl". In GNU grep gibt es keinen Unterschied in der verfügbaren Funktionalität zwischen Basic- und Extended-Syntax. In anderen Implementierungen sind reguläre Basisausdrücke weniger leistungsfähig. Die folgende Beschreibung gilt für erweiterte reguläre Ausdrücke. Unterschiede für grundlegende reguläre Ausdrücke werden anschließend zusammengefasst.

Aber grep verwendet sie nicht standardmäßig - Sie benötigen den -ESchalter:

grep "(then|there)" x.x

Weil (wieder von der Manpage):

Grundlegende oder erweiterte reguläre Ausdrücke

In regulären Grundausdrücken verlieren die Metazeichen?, +, {, |, (Und) ihre besondere Bedeutung; Verwenden Sie stattdessen die Versionen mit umgekehrten Schrägstrichen \ ?, +, {, \ |, (und).

So können Sie auch verwenden:

grep "then\|there" x.x

Da die Klammern in diesem Fall überflüssig sind.

Goldlöckchen
quelle
0

Bashs elegante Schlichtheit scheint sich in der riesigen Manpage zu verlieren.

Zusätzlich zu den oben genannten hervorragenden Lösungen würde ich versuchen, Ihnen einen Spickzettel zu geben, wie bash Anweisungen analysiert und interpretiert . Anhand dieser Roadmap analysiere ich dann die vom Fragesteller vorgestellten Beispiele, damit Sie besser verstehen, warum sie nicht wie beabsichtigt funktionieren.


Hinweis: Shell-Skriptzeilen werden direkt verwendet. Eingegebene Eingabezeilen werden zunächst in der Historie erweitert.

Jede Bash-Zeile wird zuerst mit einem Token versehen oder mit anderen Worten in sogenannte Token zerlegt . (Das Token wird vor allen anderen Erweiterungen ausgeführt, einschließlich geschweifte Klammer, Tilde, Parameter, Befehl, Arithmetik, Prozess, Wortteilung und Dateinamenerweiterung.)

Ein Token bedeutet hier einen Teil der Eingabezeile, der durch eines der folgenden speziellen Metazeichen getrennt ist:

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bash verwendet viele andere Sonderzeichen, aber nur diese 10 erzeugen die ersten Token.

Da diese Metazeichen jedoch manchmal auch in einem Token verwendet werden müssen, muss es eine Möglichkeit geben, ihre spezielle Bedeutung zu beseitigen. Dies nennt man Flucht. Entweichenden erfolgte entweder durch eine Kette von einem oder mehreren Zeichen zu zitieren, (dh 'xx..', "xx..") oder durch einen individuellen Charakter mit einem Back-Slash Vorfixierung (dh \x). (Es ist etwas komplizierter, da die Anführungszeichen auch zitiert werden müssen und weil doppelte Anführungszeichen nicht alles zitieren, aber diese Vereinfachung reicht vorerst aus.)

Verwechseln Sie Bash-Zitate nicht mit der Idee, eine Textfolge wie in anderen Sprachen zu zitieren. Was sich zwischen Anführungszeichen in Bash befindet, sind keine Zeichenfolgen, sondern Abschnitte der Eingabezeile, bei denen Metazeichen maskiert sind, um Token nicht zu begrenzen.

Beachten Sie, dass es einen wichtigen Unterschied zwischen 'und gibt ", aber das ist für einen anderen Tag.

Die verbleibenden nicht entkappten Metazeichen werden dann zu Token-Trennzeichen.

Beispielsweise,

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

Im ersten Beispiel gibt es zwei Token, die von einem Leerzeichenbegrenzer erzeugt werden: echound xyz.

Ebenso im 2. Beispiel.

Im dritten Beispiel wird das Semikolon entkam, so gibt es 4 - Token von einem Leerzeichen Trennzeichen erzeugt, echo, x;, echo, und y. Das erste Token wird dann als Befehl ausgeführt und verwendet die nächsten drei Token als Eingabe. Beachten Sie, dass der 2. echonicht ausgeführt wird.


Die wichtige Sache zu erinnern , dass die bash erste Blicke zu entkommen Zeichen sind ( ', ", und \) und sucht dann nach unescaped Meta-Zeichenbegrenzern, in dieser Reihenfolge.

Wenn nicht, dienen diese 10 Sonderzeichen als tokenBegrenzer. Einige von ihnen haben auch eine zusätzliche Bedeutung, aber in erster Linie sind sie Token-Begrenzer.


Was grep erwartet

In dem obigen Beispiel grep diese Token benötigt, grep, string, filename.

Der erste Versuch der Frage war:

$ grep (then | there) xx

In diesem Fall (, )und |sind unescaped Meta - Zeichen und so dazu dienen , den Eingang in diese Token aufgeteilt: grep, (, then, |, there, ), und x.x. grep sehen will grep, then|thereund x.x.

Der zweite Versuch der Frage war:

grep "(then | there)" xx

Diese tokenizes zu grep, (then|there), x.x. Sie können dies sehen, wenn Sie grep gegen echo austauschen:

echo "(dann | dort)" xx
(dann | dort) xx

Elliptische Ansicht
quelle