Wie kann echo
und printf
behandeln Schrägstriche in zsh
, bash
und andere Schalen?
Unter zsh bekomme ich folgendes Verhalten:
$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz
Unter Bash scheinen die Dinge etwas konsistenter zu sein:
bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$
Aber konkreter: Wie kann ich eine Zeichenfolge mit Backslashes übergeben, z. B\\foo\bar\something
.:
echo
printf
print
und genau die gleiche Zeichenfolge bekommen? (in zsh
und bash
)?
Hier ist ein weiteres Experiment mit Funktionen in zsh:
function foo
{
echo -E '$1'
}
$ foo \\here\is\some\path
$1
Wie kann ich es nur drucken lassen \\here\is\some\path
?
Update (Hinweis: Dies wurde jetzt in Stephanes Kommentar beantwortet.)
Ich habe in zsh 5.0.2 Folgendes versucht:
function foo
{
printf '$s\n' $1
}
foo '\\some\path'
Aber das druckt $s
?
printf
,echo
ist in dieser Hinsicht nicht tragbar.'
durch"
und rufen Sie sie auf mit: foo '\\ here \ is \ some \ path' (andernfalls erhält die aufrufende Shell die Möglichkeit, das '\' zu interpretieren, bevor sie zur Funktion gelangt)'$s\n'
wenn sie hätte verwendet werden sollen'%s\n'
.Antworten:
zsh
echo
verhält sich wiebash
im UNIX-Modus wie gewohnt. Das heißt, es wird\b
auf das ASCII-BS-Zeichen erweitert, wie es die UNIX-Spezifikation erfordert.Verwenden Sie nicht
echo
, um beliebige Zeichenfolgen anzuzeigen. Verwenden Sieprintf
:print -r -- "$1"
funktioniert auch aber istksh
/zsh
spezifisch.echo -E - "$1"
arbeiten mitzsh
und ich glaube einige BSDs.funktioniert in jeder Bourne-ähnlichen Hülle, selbst in jenen aus einigen Jahrzehnten, in denen es keinen
printf
Befehl gab, aber einen neuen Prozess hervorbrachte, und ist heutzutage wirklich nicht mehr notwendig, wie wir es jetztprintf
überall haben.Übrigens müssen Sie Backslashes in einer Shell-Befehlszeile vermeiden, da dies etwas Besonderes für die Shell ist (jede Shell außer
rc
). Also:foo \\foo\bar
würde die"\foo\bar"
Zeichenfolge übergeben, anfoo
die der verlorene Backslash nicht neu erfunden werden kann.quelle
printf '%s\n' "$var"
funktioniert die Konstruktion für mich über die Befehlszeile (zsh 5.0.2
dh die neueste), aber nicht innerhalb einer Funktion (siehe mein Update im OP). Warum?printf '%s\n'
nichtprintf '$s\n'
du willst. Beachten Sie, dass Sie Variablen in anderen Shells alszsh
("$1"
, nicht$1
) angeben müssen und die Syntax der Standardfunktionsdefinitionfoo() { ...; }
, obwohl jede Shell diesbash
zulässtfoo() any-command
,function foo { .... }
dieksh
Syntax ist.neue Antwort: lies -r var
und anzuzeigen:
sollte arbeiten.
Also für deine foo Funktion:
alte Antwort unten (nicht antwortend, aber vielleicht nützlich ^^)
Ersetzen Sie einfach jedes
\
durch\\
, um der Shell zu sagen, "dass es ein Literall ist, den\
ich will". Andernfalls (zum Beispiel in zsh, in Ihrem Beispiel) könnte dies durchaus\b
"1 Rücktaste" oder was auch immer bedeuten.Sie könnten zum Beispiel sed verwenden:
(Sehen Sie, wie Sie dort auch "\" entkommen müssen, um sed dasselbe zu sagen: "Es ist ein Literall" \ "Ich möchte) (und beachten Sie, dass ich es mit '' und nicht" "umgeben habe, um zu vermeiden, dass die Shell interpretiert wird das meiste auch)
quelle
read -r var
aber auf Eingabe von zu wartenSTDIN
. Was ist, wenn ich es als Argument weitergebe? (zB foo\\here\is\some\path
)Im Allgemeinen kann man nicht, weil Backslash ist die Escape - Zeichen (und als solche hat entgangen sein , wenn sein wörtlicher Wert erforderlich ist). BASH bietet zu diesem Zweck einfache Anführungszeichen. Sie können jedoch kein einfaches Anführungszeichen innerhalb einer Zeichenfolge in einfachen Anführungszeichen verwenden.
Was die
echo
Diskrepanz betrifft, handelt es sich um eine integrierte Diskrepanz, die sich zwischen den Shells (bis zu einem gewissen Grad) unterschiedlich verhalten kann. Zum Beispiel hat das eingebaute BASH eine-e
Option, die es anweist, Backslash-Sequenzen zu interpretieren - damit erhalten Sie das Verhalten, das Sie in der Z-Shell gesehen haben.quelle