Ich habe ein kleines Open-Source-Projekt, das ich aus verschiedenen Gründen versucht habe, in einem einigermaßen portablen Shell-Skript zu schreiben. Die automatisierten Integrationstests prüfen unter anderem, ob feindliche Zeichen in Pfadausdrücken richtig behandelt werden.
Benutzer mit /bin/sh
bereitgestellt von bash
sehen einen Fehler in einem Test, den ich auf Folgendes vereinfacht habe:
echo "A bug\\'s life"
echo "A bug\\\\'s life"
Bei Bash wird das erwartete Ergebnis erzielt:
A bug\'s life
A bug\\'s life
Mit dash, gegen das ich mich entwickelt habe, macht es das:
A bug\'s life
A bug\'s life
Ich würde gerne denken, dass ich keinen Fehler im Bindestrich gefunden habe, dass mir stattdessen möglicherweise etwas fehlt. Gibt es dafür eine rationale Erklärung?
Antworten:
Im
Da es sich um doppelte Anführungszeichen handelt und diese in doppelten Anführungszeichen
\
besonders sind, wird die erste\
von der Shell als Escape / Quoting der zweiten verstanden\
. Es wird also einA bug\'s life
Argument an weitergegebenecho
.Hätte genau das gleiche erreicht. Da dies
'
in doppelten Anführungszeichen nicht besonders ist, wird das\
nicht entfernt, sodass es genau das gleiche Argument ist, an das übergeben wirdecho
.Wie unter Warum ist printf besser als Echo erklärt? Es gibt viele Unterschiede zwischen den
echo
Implementierungen.In Unix-konformen Implementierungen wie
dash
's\
wird verwendet, um Escape-Sequenzen einzuführen:\n
für Newline,\b
für Backspace,\0123
für Oktalsequenzen ... und\\
für Backslash selbst.Einige (Nicht-POSIX-) erfordern eine
-e
Option dafür oder tun dies nur, wenn sie sich im Konformitätsmodus befinden (wiebash
wenn sie mit den richtigen Optionen wie fürsh
OS / X erstellt wurden oder wenn sieSHELLOPTS=xpg_echo
in der Umgebung aufgerufen werden).Im Standard (nur Unix-Standard; POSIX lässt das Verhalten nicht spezifiziert)
echo
s,gleich wie:
gibt einen Backslash aus,
bash
wenn Sie sich nicht im Konformitätsmodus befinden:gibt zwei Backslashes aus.
Am besten vermeiden
echo
undprintf
stattdessen verwenden:Was in diesem Fall in allen
printf
Implementierungen gleich funktioniert .quelle
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:
Wenn die Zeichenfolge als erstes Argument verwendet wird, sind einige Zeichen speziell.
Ein
\\
Paar repräsentiert eine Single\
und\T
eine SingleT
:Jedes der vier Paare
\\
verwandelte sich in ein einzelnes\
und das letzte\T
in einT
.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:
Dann wird der Bindestrich gedruckt (
dash ./script
):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):Wenn das verwendete Zeichen ein ist
a
, für Bindestrich:Und für Bash:
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.
Beachten Sie, dass die Shell eine Aktion für den Backslash in doppelten Anführungszeichen ausführt.
Mit diesem Code:
Beide Effekte werden hinzugefügt und wir erhalten Folgendes:
Für Dash ist es noch schwerer:
quelle