Ich hatte kürzlich Probleme mit einigen regulären Ausdrücken in der Befehlszeile und stellte fest, dass für die Suche nach einem umgekehrten Schrägstrich unterschiedliche Anzahlen von Zeichen verwendet werden können. Diese Zahl hängt von der für den regulären Ausdruck verwendeten Anführungszeichen ab (keine, einfache Anführungszeichen, doppelte Anführungszeichen). In der folgenden Bash-Sitzung erfahren Sie, was ich meine:
echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file
Das bedeutet, dass:
- Ohne Anführungszeichen kann ich einen Backslash mit 4-7 tatsächlichen Backslashes abgleichen
- mit doppelten Anführungszeichen kann ich einen Backslash mit 3-6 tatsächlichen Backslashes abgleichen
- Mit einfachen Anführungszeichen kann ich einen Backslash mit 2-3 tatsächlichen Backslashes abgleichen
Ich verstehe, dass ein zusätzlicher Backslash von der Shell ignoriert wird (aus der Bash-Manpage):
"Ein Backslash (\) ohne Anführungszeichen ist das Escape-Zeichen. Es behält den Literalwert des nächsten folgenden Zeichens bei."
Dies gilt nicht für Beispiele mit einfachen Anführungszeichen, da in einfachen Anführungszeichen kein Escapezeichen verwendet wird.
Ein zusätzlicher Backslash wird vom grep-Befehl ignoriert ("\ c" wird nur mit "c" maskiert, dies ist jedoch genau das Gleiche wie "c", da "c" in einer Regex keine besondere Bedeutung hat).
Dies erklärt das Verhalten des Beispiels mit einfachen Anführungszeichen, aber ich verstehe die beiden anderen Beispiele nicht wirklich, insbesondere, warum es einen Unterschied zwischen nicht in Anführungszeichen gesetzten und nicht in Anführungszeichen gesetzten Zeichenfolgen gibt.
Wieder ein Zitat aus der Bash-Manpage:
Msgstr "Das Einschließen von Zeichen in doppelte Anführungszeichen behält den Literalwert aller Zeichen in den Anführungszeichen bei, mit Ausnahme von $,`, \ und, wenn die Verlaufserweiterung aktiviert ist,!. "
Ich habe dasselbe mit GNU awk (zB awk /ab\cd/{print} file
) versucht, mit den gleichen Ergebnissen.
Perl zeigt jedoch unterschiedliche Ergebnisse (unter Verwendung von zB perl -ne
"/ab\\cd/"\&\&print file
):
- Ohne Anführungszeichen kann ich einen Backslash mit 4-5 tatsächlichen Backslashes abgleichen
- mit doppelten Anführungszeichen kann ich einen Backslash mit 3-4 tatsächlichen Backslashes abgleichen
- Mit einfachen Anführungszeichen kann ich einen Backslash mit 2 tatsächlichen Backslashs abgleichen
Kann jemand den Unterschied zwischen nicht zitierten und doppelten regulären Zeichenfolgen in der Befehlszeile für grep und awk erklären? Ich bin nicht sonderlich an einer Erklärung von Perls Verhalten interessiert, da ich normalerweise keine Perl-Einzeiler verwende.
quelle
printf "\ntest"
fügt vor "test" eine neue Zeile ein, obwohl"\n"
sie"n"
von der Shell in doppelte Anführungszeichen übersetzt werden sollte ... (so sollte das erwartete Ergebnis z "\ ntest", "ntest". Wir sollten uns angewöhnen, zu schreiben:printf "\\ntest"
oderprintf '\ntest'
, aber irgendwie sehe ich viel Skript, das stattdessen auf der Kuriosität beruht.Dieser Link beschreibt Bash Quotes und Escaping
Ihre Frage befasst sich mit den ersten drei Abschnitten.
Unten sehen Sie eine Tabelle, wie die Zeichenfolgen
bash
sie weiterleitengrep
und wiegrep
sie intern weiter interpretiert werden.Schauen wir uns zuerst an
echo "#ab\\cd" > file
.Im schwach zitierten ("")
"#ab\\cd"
ist das\\
ein Escapezeichen,\
dasfile
als einzelnes Literal übergeben wird\
. Also,file
enthältab\cd
Nun zu Ihren Befehlen: Die folgende Tabelle kann Ihnen helfen, zu sehen, was bei jedem Anruf tatsächlich passiert. Das
*
zeigt diejenigen, die dem Dateiinhalt entsprechen. Es geht eigentlich nur darum, die Escape-Regeln von bash anzuwenden, wie auf der Webseite, wobei insbesondere auf die Antwort von daniel kullmann hingewiesen wird , in der er sich auf das Escape- Verhalten in einer Situation mit schwachen Zitaten bezieht .quelle