Erkennt bash eine Variablendeklaration als Zeichenfolge, wenn Sie keine Anführungszeichen setzen?

8
name=Jackson
echo $name

Dies zeigt Jackson an.

name="Jackson"
echo $name

Dies zeigt auch Jackson an.

Ich gehe also davon aus, dass durch Setzen von Anführungszeichen um eine Variable eine Zeichenfolge erstellt wird. Was wäre der Name = Jackson technisch? Würde es auch als String erkannt werden?

John
quelle
Es gibt einen Unterschied: versuchen Sie name=Michael Jackson ; echo "$name"und name="Michael Jackson" ; echo "$name". Sehr verschieden. Setzen Sie normalerweise immer umgebende Anführungszeichen, wenn Sie Variablen definieren und verwenden. cd "${var}"ist viel besser als cd $vardas, was stillschweigend zum Homedir gehen würde, anstatt zu protestieren, wenn var nicht definiert ist ... Es sei denn, Sie müssen jedes einzelne Element explizit aufrufen, dh in afor i in $var ; do something ; done
Olivier Dulac
Wenn Sie sagen, name=Michael Jackson ;Sie setzen eine Variable "name" auf einen Wert "Michael" und rufen ein Programm / cmd "Jackson" auf. Bash wird einen Fehler mit der Meldung "Befehl nicht gefunden" erneut abstimmen, da bash nach einem Programm namens "Jackson" sucht. Am Ende ist die Variable "Name" also nicht gesetzt.
RKA

Antworten:

6

Linux-Umgebungsvariablen sind immer Zeichenfolgen. Die Anführungszeichen werden nur benötigt, wenn Ihre Zeichenfolge Sonderzeichen (Shell-Metazeichen oder Leerzeichen) enthält. Shell-Metazeichen sind:

<>()[]{}*?$|&#\;`'"

Mit $, \ und `reichen die doppelten Anführungszeichen nicht aus, da sie sogar in ihnen erweitert werden. Dort benötigen Sie entweder einfache Anführungszeichen oder maskieren sie mit \.

Wie in einem Kommentar erwähnt, hat bash spezielle typisierte Variablen, die jedoch selten benötigt werden. Standardmäßig sind alle bash-Variablen auch Zeichenfolgen.

Michael Suelmann
quelle
3
+1, weil der Kern der Antwort korrekt ist. Fortgeschrittenere Shells haben jedoch andere Datentypen als nur Zeichenfolgen. Mit Bash können Sie beispielsweise typeset -i foo=2eine Ganzzahlvariable $foomit dem Wert abrufen 2.
Warren Young
1
@WarrenYoung Inwiefern unterscheidet sich das von foo=2?
Goldlöckchen
1
Nb. In bash gibt es keine "Ganzzahlvariable": tldp.org/LDP/abs/html/untyped.html Sie sind immer noch Zeichenfolgen. typeset -i foo=2ist genau das gleiche wie foo=2und foo="2".
Goldlöckchen
1
@goldilocks Es ist nicht genau das gleiche. Führen Sie aus foo=0x${foo}; echo $foo"oder foo=bar;echo $foosehen Sie einen Unterschied im Verhalten. Es gibt definitiv ganzzahlige Variablen in bash.
Jlliagre
1
@goldilocks declare -i x=123456789012345678901234567890;echo ${#x}würde anzeigen, 30wenn das wahr wäre, aber das ist nicht der Fall.
Jlliagre
5

Bash ist nicht stark typisiert; 1 Der einzige signifikante Unterschied besteht zwischen skalaren und zusammengesetzten Typen (Arrays). Skalare werden immer als Zeichenfolgen betrachtet , aber es gibt "numerische Zeichenfolgen", die arithmetisch verwendet werden können:

a="5"
b=10

echo "$a + $b = "$(($a+$b)); 

Eine "numerische Zeichenfolge" ist einfach eine Zeichenfolge, die nur Ziffern enthält und daher in einen ganzzahligen Wert konvertiert werden kann. Alle Skalarwerte in bash sind immer noch nur Zeichenfolgen, und die Anführungszeichen in der Deklaration hier sind irrelevant. a=5ist genau das gleiche wie a="5". Wenn Sie vergleichen $aund $bverwenden (z. B.) -lt, werden sie als Zahlen behandelt. Wenn Sie sie mit vergleichen, werden <sie lexikographisch behandelt. Es ist der Operator / Kontext, der die Bestimmung vornimmt, kein Merkmal der Variablen.

Sie können eine Variable auch mit einem "Integer-Flag" deklarieren. Dadurch wird der deklarierte Wert als arithmetischer Ausdruck interpretiert:

x=10/2
echo "$x" # output: 10/2
declare -i x=10/2
echo "$x" # output: 5
declare -i x=what
echo "$x" # output: 0  

Anschließend wird alles, was dieser Variablen zugewiesen ist, arithmetisch interpretiert:

a=5
declare -i b=10
a=$a/5
b=$b/5
echo "$a $b" #output: 5/5 2
a=hello
b=world
echo $a$b #output hello0

Der Inhalt der Variablen ist jedoch immer noch eine (numerische) Zeichenfolge. Das Integer-Flag schränkt den Inhalt der Zeichenfolge ein und wirkt sich auf die Interpretation der ihm zugewiesenen Werte aus.

1 Es ist auch keine einfache dynamische Eingabe, wie der Fall der deklarierten Ganzzahl zeigt. Vielleicht könnten wir es eine Art Enten-Typisierung nennen , oder es ist gemäß dem Bash Advanced Scripting Guide "untypisiert".

Goldlöckchen
quelle
1
Das Deklarieren einer Variablen als Ganzzahl hat definitiv nachfolgende Konsequenzen. Ab diesem Zeitpunkt kann die Variable nicht mehr zum Speichern von (zufälligen) Zeichenfolgen verwendet werden.
Jlliagre
@jlliagre Du hast mich erwischt. Bearbeitet.
Goldlöckchen
@goldilocks "Bash ist nicht stark typisiert; 1 Der einzige signifikante Unterschied besteht zwischen skalaren und zusammengesetzten Typen (Arrays). Skalare werden immer als Zeichenfolgen betrachtet." Darf ich fragen, woher stammen diese Informationen? Ich konnte es in keiner Bash-Dokumentation finden.
Yroc
@yroc Es gibt dies aus dem "Advanced Scripting Guide": tldp.org/LDP/abs/html/untyped.html (hat das in die Fußnote oben eingearbeitet). Darüber hinaus würde ich sagen, dass ich nur das Offensichtliche gesagt habe: Die Tatsache, dass es per Definition keine expliziten Typen gibt, bedeutet, dass es nicht stark typisiert ist.
Goldlöckchen
1

Es gibt einen Unterschied: versuchen Sie es

unset name
name="Michael Jackson" ; echo "$name" 

und

unset name #to reset name, see comments
name=Michael Jackson ; echo "$name"

Es ist ganz anders: Am 2. wird versucht, den Befehl "Jackson" zu starten und ihm die Umgebung "name = Michael" zu übergeben. Es wird sich also beschweren, dass "Jackson: Befehl nicht gefunden" Ich muss den unset nameNamen "Zurücksetzen" hinzufügen , da der name=MichaelTeil der nächsten Zeile nur an den Befehl "Jackson" (und nur an diesen Befehl) übergeben wird und daher NICHT ist auf der aufrufenden Shell-Ebene erledigt! (was daher immer noch den name="Michael Jackson"Befehl vom 1. Befehl haben würde, wenn wir ihn nicht ""vor unserem 2. Versuch zurücksetzen würden. Der "echo $ name" würde also verwirrenderweise immer noch "Michael Jackson" anzeigen, wenn wir diesen 1. Versuch nicht vergessen würden .)

In gewohnt, immer setzen doppelte Anführungszeichen umgeben , wenn Sie definieren, und vor allem , wenn Sie Variablen verwenden.

cd "${var}" 

ist viel besser als

cd $var 

Die 2. Version würde stillschweigend zum Homedir gehen, anstatt zu protestieren, wenn $ var nicht definiert ist ...

Dann nehmen Sie nur aus den umliegenden doppelten Anführungszeichen nur , wenn Sie wissen , dass Sie benötigen jeweils Elemente der variablen, dh in einem trennen:

for i in $var ; do something_using_i ; done
Olivier Dulac
quelle