Was sind in Bash die Unterschiede zwischen einfachen Anführungszeichen (''
) und doppelten Anführungszeichen (""
)?
Für alle, die nicht wissen, was "interpolieren" bedeutet: de.wikipedia.org/wiki/Zeichenketteninterpolation
Was sind in Bash die Unterschiede zwischen einfachen Anführungszeichen (''
) und doppelten Anführungszeichen (""
)?
Einfache Anführungszeichen werden nichts interpolieren, aber doppelte Anführungszeichen schon. Zum Beispiel: Variablen, Backticks, bestimmte \
Escapes usw.
Beispiel:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Das Bash-Handbuch sagt hierzu:
Das Einklammern von Zeichen in einfachen Anführungszeichen (
'
) bewahrt den wörtlichen Wert jedes Zeichens innerhalb der Anführungszeichen. Ein einfaches Anführungszeichen darf auch innerhalb von einfachen Anführungszeichen nicht auftreten, auch nicht wenn es von einem Backslash vorangestellt wird.Das Einklammern von Zeichen in doppelte Anführungszeichen (
"
) bewahrt den wörtlichen Wert aller Zeichen innerhalb der Anführungszeichen, mit Ausnahme von$
,`
,\
und, wenn die Historienerweiterung aktiviert ist,!
. Die Zeichen$
und`
behalten ihre spezielle Bedeutung in doppelten Anführungszeichen bei (siehe Shell-Expansions). Der Backslash behält seine spezielle Bedeutung nur bei gefolgt von einem der folgenden Zeichen:$
,`
,"
,\
oder Zeilenumbruch. Innerhalb von doppelten Anführungszeichen werden Backslashes, die von einem dieser Zeichen gefolgt werden, entfernt. Backslashes, die Zeichen ohne besondere Bedeutung vorangehen, bleiben unverändert. Ein doppeltes Anführungszeichen kann innerhalb von doppelten Anführungszeichen durch ein vorangestellten Backslash zitiert werden. Wenn aktiviert, erfolgt die Historienerweiterung, es sei denn, ein in doppelten Anführungszeichen erscheinendes!
ist mit einem Backslash maskiert. Der vorangehende Backslash vor dem!
wird nicht entfernt.Die speziellen Parameter
*
und@
haben eine besondere Bedeutung, wenn sie in doppelten Anführungszeichen stehen (siehe Shell Parameter Expansion).
Für alle, die nicht wissen, was "interpolieren" bedeutet: de.wikipedia.org/wiki/Zeichenketteninterpolation
Was ist, wenn Sie einen git_prompt
verwenden, den git bereitstellt? Es wird vorgeschlagen, es so zu verwenden: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, git prompt. Laut diesem sollte das nicht funktionieren. Gibt es etwas Besonderes an den PS#
Variablen? Oder warum funktioniert es, wenn keine Interpolation erfolgt?
@ekiim Dieser genaue Text wird unverändert in PS1
eingestellt. Versuche echo $PS1
, um zu sehen, was ich meine. Aber PS1
wird ausgewertet, bevor es angezeigt wird (siehe den PROMPTING
Abschnitt in der Bash-Manpage). Um dies zu testen, versuche PS1='$X'
. Du wirst keine Eingabeaufforderung haben. Führe dann X=foo
aus und plötzlich lautet deine Eingabeaufforderung "foo" (wenn PS1
beim Setzen anstelle von Anzeigen ausgewertet worden wäre, hättest du immer noch keine Eingabeaufforderung).
Die akzeptierte Antwort ist großartig. Ich erstelle eine Tabelle, die beim schnellen Verständnis des Themas hilft. Die Erklärung beinhaltet eine einfache Variable a
sowie ein indexiertes Array arr
.
Wenn wir setzen
a=apfel # eine einfache Variable
arr=(apfel) # ein indexiertes Array mit einem Element
und dann den Ausdruck in der zweiten Spalte mit echo
ausgeben, erhalten wir das Ergebnis / Verhalten, das in der dritten Spalte gezeigt wird. Die vierte Spalte erklärt das Verhalten.
#
Ausdruck
Ergebnis
Kommentare
1
"$a"
apfel
Variablen werden innerhalb von ""
erweitert
2
'$a'
$a
Variablen werden innerhalb von ''
nicht erweitert
3
"'$a'"
'apfel'
''
hat innerhalb von ""
keine besondere Bedeutung
4
'"$a"'
"$a"
""
wird innerhalb von ''
wörtlich behandelt
5
'\''
ungültig
ein '
kann innerhalb von ''
nicht escaped werden; verwenden Sie "'"
oder $'\''
(ANSI-C quoting)
6
"rot$arocks"
rot
$arocks
erweitert nicht $a
; verwenden Sie ${a}rocks
, um $a
zu erhalten
7
"rotapfel$"
rotapfel$
$
gefolgt von keinem Variablennamen ergibt $
8
'\"'
\"
\
hat innerhalb von ''
keine besondere Bedeutung
9
"\'"
\'
\'
wird innerhalb von ""
interpretiert, hat aber keine Bedeutung für '
10
"\""
"
\"
wird innerhalb von ""
interpretiert
11
"*"
*
Glob funktioniert nicht innerhalb von ""
oder ''
12
"\t\n"
\t\n
\t
und \n
haben innerhalb von ""
oder ''
keine besondere Bedeutung; verwenden Sie ANSI-C quoting
13
"`echo hallo`"
hallo
``
und $()
werden innerhalb von ""
ausgewertet (Backticks bleiben im tatsächlichen Output erhalten)
14
'`echo hallo`'
`echo hallo`
``
und $()
werden innerhalb von ''
nicht ausgewertet (Backticks bleiben im tatsächlichen Output erhalten)
15
'${arr[0]}'
${arr[0]}
Array-Zugriff innerhalb von ''
ist nicht möglich
16
"${arr[0]}"
apfel
Array-Zugriff funktioniert innerhalb von ""
17
$'$a\''
$a'
Einfache Anführungszeichen können innerhalb des ANSI-C quoting escaped werden
18
"$'\t'"
$'\t'
Das ANSI-C quoting wird innerhalb von ""
nicht interpretiert
19
'!befehl'
!befehl
Das History Expansion-Zeichen '!'
wird innerhalb von ''
ignoriert
20
"!befehl"
befehl args
expandiert zum letzten Befehl, der zu "befehl"
passt
21
$'!befehl'
!befehl
Das History Expansion-Zeichen '!'
wird innerhalb von ANSI-C Quotes ignoriert
Siehe auch:
Die akzeptierte Antwort besagt am Ende Die speziellen Parameter * und @ haben eine besondere Bedeutung, wenn sie in Anführungszeichen stehen
, also wie kommt es dazu, dass "*"
in *
resultiert?
@Karl-AnderoMere, weil sie in diesem Fall überhaupt nicht als Parameter erweitert werden. "$@"
und "$*"
sind Parametererweiterungen. "@"
und "*"
sind es nicht.
Wenn Sie sich auf das beziehen, was passiert, wenn Sie etwas echoen, werden die einfachen Anführungszeichen wortwörtlich das ausgeben, was Sie zwischen ihnen haben, während die doppelten Anführungszeichen Variablen zwischen ihnen auswerten und den Wert der Variablen ausgeben werden.
Zum Beispiel, das hier
#!/bin/sh
MYVAR=sometext
echo "Doppelte Anführungszeichen geben Ihnen $MYVAR"
echo 'Einfache Anführungszeichen geben Ihnen $MYVAR'
wird das hier ausgeben:
Doppelte Anführungszeichen geben Ihnen sometext
Einfache Anführungszeichen geben Ihnen $MYVAR
Andere haben es sehr gut erklärt, und ich möchte nur etwas mit einfachen Beispielen geben.
Einfache Anführungszeichen können um Text herum verwendet werden, um zu verhindern, dass die Shell Sonderzeichen interpretiert. Dollarzeichen, Leerzeichen, Ka- undersand, Sterne und andere Sonderzeichen werden alle ignoriert, wenn sie in einfache Anführungszeichen eingeschlossen sind.
echo 'Allerlei Dinge werden in einfachen Anführungszeichen ignoriert, wie $ & * ; |.'
Es wird folgendes ausgegeben:
Allerlei Dinge werden in einfachen Anführungszeichen ignoriert, wie $ & * ; |.
Das einzige, was nicht in einfache Anführungszeichen gesetzt werden kann, ist ein einfaches Anführungszeichen.
Doppelte Anführungszeichen verhalten sich ähnlich wie einfache Anführungszeichen, außer dass doppelte Anführungszeichen es der Shell immer noch erlauben, Dollarzeichen, Backticks und Backslashes zu interpretieren. Es ist bereits bekannt, dass Backslashes verhindern, dass ein einzelnes Sonderzeichen interpretiert wird. Dies kann innerhalb doppelter Anführungszeichen nützlich sein, wenn ein Dollarzeichen als Text anstelle einer Variablen verwendet werden muss. Es erlaubt auch doppelte Anführungszeichen zu escapen, damit sie nicht als das Ende einer zitierten Zeichenkette interpretiert werden.
echo "So können wir einfache ' und doppelte \" Anführungszeichen innerhalb von doppelten Anführungszeichen nutzen."
Es wird folgendes ausgegeben:
So können wir einfache ' und doppelte " Anführungszeichen innerhalb von doppelten Anführungs- zeichen nutzen.
Es kann auch bemerkt werden, dass das Apostroph, das sonst als Beginn einer zitierten Zeichenkette interpretiert werden würde, innerhalb doppelter Anführungszeichen ignoriert wird. Variablen hingegen werden innerhalb doppelter Anführungszeichen interpretiert und mit ihren Werten substituiert.
echo "Die aktuelle Oracle SID ist $ORACLE_SID"
Es wird folgendes ausgegeben:
Die aktuelle Oracle SID ist test
Backticks sind vollkommen anders als einfache oder doppelte Anführungszeichen. Anstatt verwendet zu werden, um die Interpretation von Sonderzeichen zu verhindern, zwingen Backticks tatsächlich die Ausführung der Befehle, die sie einschließen. Nachdem die eingeschlossenen Befehle ausgeführt wurden, wird ihre Ausgabe anstelle der Backticks in der originalen Zeile substituiert. Das wird klarer mit einem Beispiel.
today=`date '+%A, %B %d, %Y'`
echo $today
Es wird folgendes ausgegeben:
Montag, September 28, 2015
Ich mag diese Antwort, weil sie deutlich sagt Das einzige, was nicht in einfachen Anführungszeichen stehen kann, ist ein einfaches Anführungszeichen
. Lass mich nur hinzufügen, dass Backticks veraltet sind, während $() POSIX-kompatibel ist, daher sollte man letzteres bevorzugen.
Da dies die de-facto-Antwort auf das Umgängen mit Anführungszeichen in Bash ist, werde ich einen weiteren Punkt hinzufügen, der in den obigen Antworten übersehen wurde, nämlich den Umgang mit den arithmetischen Operatoren in der Shell.
Die Bash-Shell unterstützt zwei Möglichkeiten, arithmetische Operationen durchzuführen, eine definiert durch das integrierte let
-Kommando und die andere der $((..))
-Operator. Das erste wertet einen arithmetischen Ausdruck aus, während das letztere eher eine zusammengesetzte Anweisung ist.
Es ist wichtig zu verstehen, dass der arithmetische Ausdruck, der mit let
verwendet wird, genauso wie andere Shell-Befehle Wortaufspaltung und Pfaderweiterung durchläuft. Daher müssen ordnungsgemäße Anführungszeichen und Escapes gesetzt werden.
Siehe dieses Beispiel bei der Verwendung von let
:
let 'foo = 2 + 1'
echo $foo
3
Die Verwendung von einfachen Anführungszeichen ist hier absolut in Ordnung, da hier keine Variablenerweiterungen erforderlich sind. Betrachten Sie einen Fall von
bar=1
let 'foo = $bar + 1'
das wäre kläglich gescheitert, da das $bar
unter einfachen Anführungszeichen nicht erweitern würde und doppelt angeführt werden müsste wie
let 'foo = '"$bar"' + 1'
Dies sollte einer der Gründe sein, warum $((..))
gegenüber let
verwendet werden sollte. Da darin der Inhalt nicht der Wortaufspaltung unterliegt. Das vorherige Beispiel mit let
kann einfach wie folgt geschrieben werden
(( bar=1, foo = bar + 1 ))
$((..))
ohne einfache Anführungszeichen zu verwendenAuch wenn $((..))
mit doppelten Anführungszeichen verwendet werden kann, hat es keinen Zweck, da das Ergebnis nicht den Inhalt enthalten kann, der doppelte Anführungszeichen benötigen würde. Achten Sie einfach darauf, dass es nicht einfach angeführt ist.
printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): ungültige Nummer
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
Vielleicht in einigen speziellen Fällen, in denen der $((..))
-Operator innerhalb eines einfach angeführten Strings verwendet wird, müssen Anführungszeichen interpoliert werden, sodass der Operator entweder unangeführt oder unter doppelten Anführungszeichen steht. Zum Beispiel, wenn Sie versuchen, den Operator in einer curl
-Anweisung zu verwenden, um jedes Mal, wenn eine Anfrage gestellt wird, einen Zähler zu übergeben, tun Sie folgendes
curl http://meinurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'
Bemerken Sie die Verwendung von verschachtelten doppelten Anführungszeichen darin, ohne die das buchstäbliche Zeichenfolge $((reqcnt++))
an das Feld requestCounter
übergeben wird.
Charles Duffy führt hier einen guten Fall für das doppelte Zitieren von $((...))
an. Es mag "ein bisschen" paranoid und ziemlich unwahrscheinlich sein, IFS=0
zum Beispiel, aber es ist sicherlich nicht unmöglich :)
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
3 Stimmen
Siehe dazu (eine mögliche plattformübergreifende Dublette): Was ist der Unterschied zwischen "...", '...', $'...' und $"..." Anführungszeichen? von Unix & Linux Stack Exchange.
3 Stimmen
Der Titel sagt Bash, aber das gilt wirklich für jede Bourne-kompatible Shell (klassische Bourne-Shell, POSIX
sh
,ash
,dash
,ksh
, und - mit einigen Vorbehalten -zsh
).0 Stimmen
Verwandt: Gibt es einen syntaktischen Unterschied zwischen einfachen und doppelten leeren Zeichenfolgen?