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.
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.