Das Problem für echo und printf hängt nur mit dem Verständnis zusammen, wenn ein rückseitig zitiertes Zeichen ein "Sonderzeichen" ist.
Am einfachsten ist es mit einem String in printf '%s' "$string"
.
In diesem Fall müssen keine Sonderzeichen verarbeitet werden, und alles, was der Befehl printf im zweiten Argument empfängt, wird unverändert gedruckt.
Beachten Sie, dass nur einfache Anführungszeichen verwendet werden:
$ printf '%s\n' '\\\\\\\\\T ' # nine \
\\\\\\\\\T # nine \
Wenn die Zeichenfolge als erstes Argument verwendet wird, sind einige Zeichen speziell.
Ein \\
Paar repräsentiert eine Single \
und \T
eine Single T
:
$ printf '\\\\\\\\\T ' # nine \
\\\\T # four \
Jedes der vier Paare \\
verwandelte sich in ein einzelnes \
und das letzte \T
in ein T
.
$ printf '\\\\\\\\\a ' # nine \
\\\\ # four \
Jedes der vier Paare \\
verwandelt sich in ein einzelnes \
und das letzte \a
in eine Glocke (BEL) (nicht druckbar).
Das gleiche passiert mit einigen Implementierungen von Echo.
Die Dash-Implementierung transformiert immer spezielle Backslash-Zeichen.
Wenn wir diesen Code in ein Skript einfügen:
set -- '\g ' '\\g ' '\\\g ' '\\\\g ' '\\\\\g ' '\\\\\\g ' '\\\\\\\g ' '\\\\\\\\g ' '\\\\\\\\\g '
for i ; do
printf '<%-14s> \t<%-9s> \t<%-14s> \t<%-12s>\n' \
"$(printf '%s ' "|$i|")" \
"$(printf "|$i|")" \
"$(echo "|$i|")" \
"$(echo -e "|$i|")" ;
done
Dann wird der Bindestrich gedruckt ( dash ./script
):
<|\g | > <|\g | > <|\g | > <-e |\g | >
<|\\g | > <|\g | > <|\g | > <-e |\g | >
<|\\\g | > <|\\g | > <|\\g | > <-e |\\g | >
<|\\\\g | > <|\\g | > <|\\g | > <-e |\\g | >
<|\\\\\g | > <|\\\g | > <|\\\g | > <-e |\\\g | >
<|\\\\\\g | > <|\\\g | > <|\\\g | > <-e |\\\g | >
<|\\\\\\\g | > <|\\\\g | > <|\\\\g | > <-e |\\\\g | >
<|\\\\\\\\g | > <|\\\\g | > <|\\\\g | > <-e |\\\\g | >
<|\\\\\\\\\g | > <|\\\\\g |> <|\\\\\g | > <-e |\\\\\g |>
Die ersten beiden Spalten sind für alle Shells gleich (printf).
Die beiden anderen ändern sich mit der spezifischen Implementierung des verwendeten Echos.
Zum Beispiel: ash ./script
(Busybox Asche):
<|\g | > <|\g | > <|\g | > <|\g | >
<|\\g | > <|\g | > <|\\g | > <|\g | >
<|\\\g | > <|\\g | > <|\\\g | > <|\\g | >
<|\\\\g | > <|\\g | > <|\\\\g | > <|\\g | >
<|\\\\\g | > <|\\\g | > <|\\\\\g | > <|\\\g | >
<|\\\\\\g | > <|\\\g | > <|\\\\\\g | > <|\\\g | >
<|\\\\\\\g | > <|\\\\g | > <|\\\\\\\g | > <|\\\\g | >
<|\\\\\\\\g | > <|\\\\g | > <|\\\\\\\\g | > <|\\\\g | >
<|\\\\\\\\\g | > <|\\\\\g |> <|\\\\\\\\\g | > <|\\\\\g | >
Wenn das verwendete Zeichen ein ist a
, für Bindestrich:
<|\a | > <| | > <| | > <-e | | >
<|\\a | > <|\a | > <|\a | > <-e |\a | >
<|\\\a | > <|\ | > <|\ | > <-e |\ | >
<|\\\\a | > <|\\a | > <|\\a | > <-e |\\a | >
<|\\\\\a | > <|\\ | > <|\\ | > <-e |\\ | >
<|\\\\\\a | > <|\\\a | > <|\\\a | > <-e |\\\a | >
<|\\\\\\\a | > <|\\\ | > <|\\\ | > <-e |\\\ | >
<|\\\\\\\\a | > <|\\\\a | > <|\\\\a | > <-e |\\\\a | >
<|\\\\\\\\\a | > <|\\\\ | > <|\\\\ | > <-e |\\\\ | >
Und für Bash:
<|\a | > <| | > <|\a | > <| | >
<|\\a | > <|\a | > <|\\a | > <|\a | >
<|\\\a | > <|\ | > <|\\\a | > <|\ | >
<|\\\\a | > <|\\a | > <|\\\\a | > <|\\a | >
<|\\\\\a | > <|\\ | > <|\\\\\a | > <|\\ | >
<|\\\\\\a | > <|\\\a | > <|\\\\\\a | > <|\\\a | >
<|\\\\\\\a | > <|\\\ | > <|\\\\\\\a | > <|\\\ | >
<|\\\\\\\\a | > <|\\\\a | > <|\\\\\\\\a | > <|\\\\a | >
<|\\\\\\\\\a | > <|\\\\ | > <|\\\\\\\\\a | > <|\\\\ | >
Dazu müssen wir die Interpretation hinzufügen, dass die Shell, in der die Befehle ausgeführt werden, möglicherweise auch für die Zeichenfolge gilt.
$ printf '%s\n' '\\\\T '
\\\\T
$ printf '%s\n' "\\\\T "
\\T
Beachten Sie, dass die Shell eine Aktion für den Backslash in doppelten Anführungszeichen ausführt.
Mit diesem Code:
tab=' '
say(){ echo "$(printf '%s' "$a") $tab $(echo "$a") $tab $(echo -e "$a")"; }
a="one \a " ; say
a="two \\a " ; say
a="t33 \\\a " ; say
a="f44 \\\\a " ; say
a="f55 \\\\\a " ; say
a="s66 \\\\\\a " ; say
a="s77 \\\\\\\a " ; say
a="e88 \\\\\\\\a " ; say
a="n99 \\\\\\\\\a " ; say
Beide Effekte werden hinzugefügt und wir erhalten Folgendes:
$ bash ./script
one \a one \a one
two \a two \a two
t33 \\a t33 \\a t33 \a
f44 \\a f44 \\a f44 \a
f55 \\\a f55 \\\a f55 \
s66 \\\a s66 \\\a s66 \
s77 \\\\a s77 \\\\a s77 \\a
e88 \\\\a e88 \\\\a e88 \\a
n99 \\\\\a n99 \\\\\a n99 \\
Für Dash ist es noch schwerer:
$ dash ./script
one one -e one
two two -e two
t33 \a t33 -e t33
f44 \a f44 -e f44
f55 \ f55 \ -e f55 \
s66 \ s66 \ -e s66 \
s77 \\a s77 \a -e s77 \a
e88 \\a e88 \a -e e88 \a
n99 \\ n99 \ -e n99 \