Was ist der Unterschied zwischen "...", "...", "..." und "..."?

49

Manchmal sehe ich Skripte alle diese verschiedenen Arten verwenden von einem Text zu zitieren: "...", '...', $'...', und $"...". Warum werden so viele verschiedene Arten von Zitaten verwendet?

Verhalten sie sich anders oder beeinflussen sie, was ich in ihnen tun kann?

Michael Homer
quelle
1
Möglicherweise standortübergreifendes Duplikat. Diese Antwort enthält eine Zusammenfassung (oder Links zu) der Semantik aller verschiedenen Arten von Anführungszeichen.
Chepner

Antworten:

66

All dies bedeutet etwas anderes, und Sie können verschiedene Dinge in sie schreiben (oder die gleichen Dinge mit unterschiedlicher Bedeutung). Unterschiedliche Arten von Anführungszeichen interpretieren unterschiedliche Escape-Sequenzen in ihnen ( \something) oder lassen variable Interpolationen ( $something) und andere Arten von Erweiterungen in ihnen zu oder lassen diese nicht zu .

Zusamenfassend:

  • '...' ist ganz wörtlich.
  • "..." erlaubt sowohl Variablen als auch eingebettete Anführungszeichen.
  • $'...'führt Zeichenausbrüche wie aus \n, erweitert aber keine Variablen.
  • $"..." ist für menschlichsprachige Übersetzungen in Bash und ksh.

'Einzelzitate'

Was immer Sie zwischen einfachen Anführungszeichen schreiben, wird buchstäblich behandelt und überhaupt nicht verarbeitet. Backslashes und Dollarzeichen haben dort keine besondere Bedeutung. Dies bedeutet, dass Sie ein Zeichen (einschließlich anderer einfacher Anführungszeichen!) Nicht mit einem umgekehrten Schrägstrich versehen, eine Variable nicht interpolieren oder keine andere Shell-Funktion verwenden können.

Alle diese Beispiele führen buchstäblich dazu, was zwischen den Anführungszeichen steht:

'hello world'                     => hello world
'/pkg/bin:$PATH'                  => /pkg/bin:$PATH
'hello\nworld'                    => hello\nworld
'`echo abc`'                      => `echo abc`
'I\'dn\'t've'                     => I\dn'tve

Das letzte ist kompliziert - es gibt zwei einfach zitierte Zeichenfolgen, die zusammen mit nicht zitiertem Text ausgeführt werden. Der erste enthält I\. Der nicht in dn\'tAnführungszeichen gesetzte Text enthält ein einfaches Anführungszeichen, das auf Shell-Ebene maskiert wird , sodass keine in Anführungszeichen gesetzte Zeichenfolge beginnt und als literales Zeichen (also, dn't) enthalten ist. Die endgültige Anführungszeichenfolge ist nur ve. All diese Elemente werden auf die übliche Art und Weise, wie die Shell funktioniert, zu einem einzigen Wort zusammengefasst.

Eine etwas gebräuchliche Redewendung zum Kombinieren von wörtlichem Text und Variablen besteht darin, sie wie folgt zusammenzuführen:

'let x="'$PATH\"

wird darin enden, dass

let x="/usr/bin:/bin"

als ein einzelnes Wort (besser doppelte Anführungszeichen $PATHals auch für alle Fälle - Leerzeichen oder Globbing Zeichen in der Variablen Wert kann auf andere Weise bearbeitet werden - aber im Interesse eines lesbaren Lauf Beispiel habe ich nicht).


"Anführungszeichen"

Innerhalb von doppelten Anführungszeichen werden zwei Arten von Erweiterungen verarbeitet, und Sie können einen Backslash verwenden, um Zeichen zu maskieren, um zu verhindern, dass Erweiterungen oder Maskierungen verarbeitet werden.

Es gibt zwei Kategorien von Erweiterungen, die in doppelten Anführungszeichen stehen:

Innerhalb der Anführungszeichen kann ein Backslash diese Erweiterungen verhindern, indem er vor das $oder gesetzt wird `. Es kann auch vor einem schließenden doppelten Anführungszeichen stehen, also \"nur "in Ihrer Zeichenfolge oder einem anderen Backslash. Jeder andere Backslash bleibt buchstäblich erhalten - es gibt keine Escapezeichen, um andere Zeichen zu erzeugen, und er wird nicht entfernt.

Einige dieser Beispiele verhalten sich anders als zuvor, andere nicht:

"hello world"                     => hello world
"/pkg/bin:$PATH"                  => /pkg/bin:/bin:/usr/bin
"hello\nworld"                    => hello\nworld
"hello\\nworld"                   => hello\nworld
"`echo abc`"                      => abc
"I\'dn\'t've"                     => I\'dn\'t've
"I'dn't've"                       => I'dn't've
"I\"dn\"t've"                     => I"dn"t've

$ 'ANSI-C quoting'

Diese Art von Anführungszeichen ermöglicht die Verarbeitung von Backslash-Escape-Zeichen im C-Stil, jedoch keine eingebetteten Variablen oder Substitutionen. Es ist die einzige Art des Zitierens, die Zeichenflucht unterstützt .

Dies ist eine Erweiterung von ksh, die jetzt auch in Bash, zsh und einigen anderen Shells unterstützt wird. Es ist noch nicht Teil des POSIX-Standards und daher können maximal portierbare Skripte es nicht verwenden, aber ein Bash- oder ksh-Skript ist kostenlos.

Alle diese Fluchten können mit ihren C Bedeutungen verwendet werden: \a, \b, \f, \n, \r, \t, \v, und die wörtliche entweicht \\, \', \", und \?. Sie unterstützen auch die Erweiterungen \e(Escape-Zeichen) und in Bash und ksh \cx(was durch Strg-x eingegeben werden würde , z. B. \cMWagenrücklauf). Shells haben eine Reihe eigener Nebenstellen.

Es erlaubt auch vier Arten von generischen Zeichen zu entkommen:

  • \nnnEin einzelnes Byte mit dem Oktalwert nnn
  • \xHHein einzelnes Byte mit Hexadezimalwert HH
  • \uHHHH, der Unicode-Codepunkt, dessen Hexadezimalindex HHHH ist
  • \UHHHHHHHH, der Unicode-Codepunkt, dessen Hexadezimalindex HHHHHHHH ist

Alle diese Ziffern sind nach der ersten optional.

$und `haben keine Bedeutung und werden buchstäblich beibehalten, sodass Sie dort keine Variable einfügen können.

$'hello world'                    => hello world
$'/pkg/bin:$PATH'                 => /pkg/bin:$PATH
$'hello\nworld'                   => hello
                                     world
$'`echo abc`'                     => `echo abc`
$'I\'dn\'t\'ve'                   => I'dn't've
$'\U1f574\u263A'                  => 🕴☺

Die meisten dieser Fluchten Sie simulieren können mit dem printfBefehl , obwohl POSIX erfordert nur \\, \a, \b, \f, \n, \r, \t, \v, und \nnnan der Arbeit dort. Sie können Befehls Substitution einzubetten , eine Verwendung printfin doppelte Anführungszeichen , wenn erforderlich: "Path:$(printf '\t')$PATH".


$ "Gebietsschema-Übersetzung"

Dies ist eine ksh- und Bash-spezifische Erweiterung zum Lokalisieren von Textzeichenfolgen in natürlicher Sprache und schlägt den Teil in den Anführungszeichen in einem Nachrichtenkatalog nach. Es führt zuerst alle Erweiterungen mit doppelten Anführungszeichen aus. Wenn der String nicht in der Übersetzungsdatenbank gefunden wird, wird er als eigene Übersetzung verwendet. Die eingebaute Annahme ist, dass die Zeichenfolgen in Englisch sind.

Sie möchten diese wahrscheinlich nicht verwenden, aber wenn Sie sie sehen, können Sie sie im Allgemeinen als reguläre Anführungszeichen behandeln.


Bemerkenswert ist, dass es keine Art von Anführungszeichen gibt, die sowohl die Erweiterung eingebetteter Parameter als auch das Entweichen eingebetteter Zeichen ermöglichen. In den meisten Fällen, in denen Sie dies wünschen, sind Sie besser dran (sicherer), wenn Sie Folgendes verwenden printf:

printf 'New path: \e[1m%s\e[0m' "/pkg/bin:$PATH:"

Dies trennt klar, welche Teile einem Zeichenverlust unterliegen und welche Datenwerte.

Ein weiterer Grund ist, dass alle diese Anführungszeichen ein einzelnes "Wort" in der Shell erzeugen, es sei denn , in Anführungszeichen wird $@eine Array-Erweiterung ${x[@]}verwendet. Beide Formen mit einem Anführungszeichen sind immer ein Wort und werden nie weiter erweitert.

Michael Homer
quelle
$"..."ist auch von ksh93 und wurde zu bash in 2.0 hinzugefügt.
Stéphane Chazelas
Es ist kein \cXin zsh. Es ist \CXoder \C-Xdort (hat \cbereits eine besondere Bedeutung in echo)
Stéphane Chazelas
'let x="'$PATH\"ist falsch in Listenkontexten in anderen Shells als zshas, $PATHdie nicht in Anführungszeichen gesetzt sind (wäre also split + glob unterworfen, was Sie hier nicht möchten).
Stéphane Chazelas
Vielleicht möchten Sie klarstellen, dass es sich um kornähnliche Muscheln handelt. Die Verarbeitung von Zitaten unterscheidet sich in csh, rc, fish ...
Stéphane Chazelas
@ StéphaneChazelas Definiere "Listenkontext".
Isaac