Warum tut
grep e\\.g\\. <<< "this is an e.g. wow"
und
grep e\.g\. <<< "this is an e.g. wow"
mach das selbe?
Wenn ich einen dritten Schrägstrich hinzufüge, hat dies auch das gleiche Ergebnis. ABER sobald ich einen vierten Schrägstrich hinzufüge, funktioniert es nicht mehr. Dies hat mit einer Frage aus einer alten Prüfung für eine Klasse zu tun. Es wurde gefragt, ob der mit zwei Backslashes funktionieren würde, um die Zeile mit "zB" auszugeben. Ich dachte ursprünglich, dass es nicht funktionieren würde, aber ich versuchte es sicherzustellen und es tat es. Was ist die Erklärung?
bash
shell
regular-expression
quoting
Wyatt Grant
quelle
quelle
\\\.
und geben,\.
aber das tut es nicht. gute FrageAntworten:
Beachten Sie zunächst, dass der einzelne Schrägstrich zu stark übereinstimmt:
Für Bash ist eine entkommene Periode dieselbe wie eine Periode. Bash gibt die Periode an grep weiter . Für grep passt ein Punkt zu allem.
Betrachten Sie nun:
Wenn Bash einen doppelten Schrägstrich sieht, reduziert er ihn auf einen einzelnen Schrägstrich und gibt diesen an grep weiter, der im ersten der drei obigen Tests, wie wir wollen, einen einzelnen Schrägstrich vor einem Punkt sieht. Das macht also das Richtige.
Mit einem dreifachen Schrägstrich reduziert Bash die ersten beiden auf einen einzigen Schrägstrich. Es sieht dann
\.
. Da eine entkommene Periode für Bash keine besondere Bedeutung hat, wird dies auf eine einfache Periode reduziert. Das Ergebnis ist, dass grep, wie wir wollen, vor einer Periode einen Schrägstrich sieht.Mit vier Schrägstrichen reduziert Bash jedes Paar auf einen einzigen Schrägstrich. Bash gibt zwei Schrägstriche und einen Punkt weiter. grep sieht die zwei Schrägstriche und einen Punkt und reduziert die beiden Schrägstriche auf einen einzigen wörtlichen Schrägstrich. Sofern die Eingabe keinen wörtlichen Schrägstrich gefolgt von einem Zeichen enthält, gibt es keine Übereinstimmungen.
Denken Sie zur Veranschaulichung daran, dass in einfachen Anführungszeichen alle Zeichen wörtlich sind. In Anbetracht der folgenden drei Eingabezeilen stimmt der Befehl grep nur in der Zeile mit dem wörtlichen Schrägstrich in der Eingabe überein:
Zusammenfassung von Bashs Verhalten
Für Bash gelten die Regeln
Zwei Schrägstriche werden auf einen einzigen Schrägstrich reduziert.
Ein Schrägstrich vor einem normalen Zeichen ist wie ein Punkt nur das normale Zeichen (Punkt).
Somit:
Es gibt eine einfache Möglichkeit, all diese Verwirrung zu vermeiden: In der Bash-Befehlszeile sollten reguläre Ausdrücke in einfache Anführungszeichen gesetzt werden. In einfachen Anführungszeichen lässt Bash alles in Ruhe.
quelle
echo
Erklärung, die zeigt, was Bash in diesen Fällen bewirkt.\.
oder.
. Für Bash sind beide gleich: Sie entsprechen einer einfachen Periode. Insgesamt ist das, was Bash an Grep liefert, für beide gleich: ein einzelner Schrägstrich, gefolgt von einem Punkt.echo
ist aufgrund der vielen Implementierungen dieses Programms keine sehr zuverlässige Methode, um Regexp zu testen. Zum Beispiel unter meinem zsh (eingebautes Echo)echo \. \\. \\\. \\\\. \\\\\.
gibt. \. \. \. \.
, aber/bin/echo \. \\. \\\. \\\\. \\\\\.
zurück. \. \. \\. \\.
. So etwasprintf "%s" ...
ist wahrscheinlich der bessere Weg.Die Ausgabe ist nur für Ihre Zeichenfolge gleich, aber im Allgemeinen bewirken diese regulären Ausdrücke unterschiedliche Funktionen. Lassen Sie uns Ihr Beispiel ein wenig ändern, indem Sie ein zweites Muster
e,g,
(mit Koma), ein drittese\.g\.
(Punkte), ein viertese\,g\,
(Koma) und eine Grep--o
Option hinzufügen, um nur übereinstimmende Teile zu drucken.Im folgenden Fall
.
passen alle Zeichen (Ankündigung''
ume.g.
, werde ich dazu kommen später)Als nächstes entkommen wir
.
mit einem Backslash\
, sodass nur das Literal.
übereinstimmt:Aber wir können
\
mit einem anderen entkommen\
, so dass das Literal\
übereinstimmt, gefolgt von.
(dh einem beliebigen Zeichen):Aber wenn wir nur
\.
nicht übereinstimmen wollen, wird\,
noch eine weitere\
benötigt, um der besonderen Bedeutung des Punktes zu entgehen:Da Sie das
''
Argument grep nicht verwendet haben , müssen Sie weitere Backslashes hinzufügen, um Backslashes bei der Shell-Interpretation zu vermeiden.quelle
Wenn Sie a
grep e\.g\.
ausführen, verbraucht die Shell den Backslash, also machen Sie agrep e.g.
, was übereinstimmt. Wenn Siegrep e\\.g\\.
a ausführen, verbraucht die Shell erneut einen Schrägstrich, und jetzt führen Sie einen ausgrep e\.\g.
, der wieder übereinstimmt. Nun sieht ein Backslash zur Shell aus\\
. Wenn Sie also haben\\
, ist die erste eine Escape-Sequenz, die zweite ein wörtlicher Backslash. Wenn Sie a ausführengrep e\\\.g\\\.
, ist dies immer noch der Fallgrep e\.\g.
, da\
vor der ersten keine Escape-Sequenz ( ) steht\
, die es zu einem Literal macht\
. Denken Sie daran, \ ist ein Backslash undgrep e\\\\.\\\\g
endet damitgrep e\\.g\\.
, was offensichtlich nicht übereinstimmt.Verwenden Sie echo (z. B.
echo grep e\\.g\\. <<< "this is an e.g. wow"
vs.echo grep e\\\\.g\\\\. <<< "this is an e.g. wow"
) , um zu sehen, wie die Shell sieht, was Sie tun.quelle
Die beiden Befehle erzeugen nur für Ihre Eingabe dieselbe Ausgabe, ansonsten sind sie jedoch unterschiedlich. Um zu verstehen, was vor sich geht, müssen wir wissen, wie der Parameter zuerst von
bash
und dann von interpretiert wirdgrep
.Flucht in Bash
\
ist ein Sonderzeichen, das die Sonderbedeutung des folgenden Zeichens einschließlich sich\
selbst aufhebt . Wenn das folgende Zeichen keine besondere Bedeutung hat, wird es unverändert übergeben. Beispiele mit Befehl und Ergebnis:echo \a
:a
- gewöhnliches entkommenes Zeichen gibt das Zeichenecho \\
:\
- Sonderzeichen entkommen gibt den Charakterecho \\\a
:\a
- Kombination speziell, gewöhnlichecho \\\\
:\\
- Kombination speziell, speziellecho
druckt die resultierende Zeichenfolge, nachdem siebash
interpretiert wurde. Weitere Informationen: Bash-Dokumentation , Bash-Hacker-Wiki , POSIX-Spezifikation ..
hat keine besondere Bedeutung inbash
. Es ist ein gewöhnlicher Charakter für die Schale. Nachfolgend sind die für Ihre Beispiele relevanten Sequenzen aufgeführt:echo .
::.
echo \.
::.
echo \\.
::\.
echo \\\.
::\.
echo \\\\.
::\\.
Einfachere Lösung für wörtliche Zeichenfolgen in Bash
Um Parameter buchstäblich zu übergeben
bash
, können Sie das einfache Anführungszeichen verwenden'
. Zwischen einfachen Anführungszeichen müssen Sie sich nicht um die besondere Bedeutung von Zeichen kümmern, da einfache Anführungszeichen das einzige Zeichen mit einer besonderen Bedeutung sind. Sie können ein einfaches Anführungszeichen einfügen, nachdem Sie den ersten Teil der Zeichenfolge eingeschlossen haben. Beispiel:echo 'part1'\''part2'
:part1'part2
Regex in grep
\
ist ein Fluchtzeichen mit ähnlicher Bedeutung wie inbash
..
ist ein Sonderzeichen, das ein einzelnes Vorkommen eines Zeichens darstellt . Siehe: POSIX-Regex , GNU-Grep-Regex . Beispiele für Regex-Ausdrücke:.
- Entspricht einem beliebigen Zeichen wiea
oder.
\.
- passt nur.
wörtlichIhre Beispiele
In der zweiten Zeile jedes Beispiel unter Ihnen gleichwertig mit einfachen Anführungszeichen werden feststellen , die
'
zeigt , welche Zeichenkette durch geführt wirdbash
zugrep
. Nach demgrep
Escape-Vorgang stimmt das einzig mögliche Sonderzeichen in den Beispielen.
mit einem beliebigen Zeichen überein. In der dritten Zeile finden Sie eine Beschreibung, mit der der Ausdruck übereinstimmt.grep e.g. <<< "this is an e.g. wow"
grep 'e.g.' <<< "this is an e.g. wow"
e
Beliebiges Zeicheng
Beliebiges Zeichen - Übereinstimmungene.g.
und möglicherweise andere Zeichenfolgen wieeagb
grep e\.g\. <<< "this is an e.g. wow"
grep 'e.g.' <<< "this is an e.g. wow"
e
Beliebiges Zeicheng
Beliebiges Zeichen - Übereinstimmungene.g.
und möglicherweise andere Zeichenfolgen wieexgy
grep e\\.g\\. <<< "this is an e.g. wow"
grep 'e\.g\.' <<< "this is an e.g. wow"
e.g.
buchstäblich - nur Übereinstimmungene.g.
grep e\\\.g\\\. <<< "this is an e.g. wow"
grep 'e\.g\.' <<< "this is an e.g. wow"
e.g.
buchstäblich - nur Übereinstimmungene.g.
grep e\\\\.g\\\\. <<< "this is an e.g. wow"
grep 'e\\.g\\.' <<< "this is an e.g. wow"
e\
irgendein Charakterg\
irgendein Charakter - stimmt nicht übereine.g.
quelle