Zitieren Sie eine Variable in der if-Anweisung des Shell-Skripts

9

z.B

if [ "$FOO" = "true" ]; then

vs.

if [ $FOO = "true" ]; then

Was ist der Unterschied? Scheint, dass beide Aussagen auch funktionieren.

Ryan
quelle
Verwenden Sie in Bash doppelte eckige Klammern, und Sie benötigen die Anführungszeichen nicht, und Sie erhalten zusätzliche Vorteile .
Bis auf weiteres angehalten.
@DennisWilliamson Nicht ganz, Sie benötigen Anführungszeichen auf der rechten Seite der Operatoren für (In-) Gleichheit und Mustervergleich.
Gilles 'SO - hör auf böse zu sein'
@ Gilles: Manchmal nicht. Für Literalzeichenfolgen mit Leerzeichen oder für Literalzeichenfolgen oder Variablen mit Glob-Zeichen, die wörtlich genommen werden sollen , muss die rechte Seite in Anführungszeichen gesetzt werden : a='foo bar'; [[ $a == "foo bar" ]]. Eine Variable, die keine Glob-Zeichen enthält, muss jedoch nicht sein : [[ $a == $a ]]. Die Worterweiterung wird nicht in doppelten eckigen Klammern ausgeführt. Und für Regex Matching, das Muster auf der rechten Seite darf nicht zitiert werden , oder es wird als Zeichenkette entnommen werden: [[ $a =~ .*oo.*r ]](das Muster in einem nicht genannten variabel sein sollte, aber stattdessen ...
. Pausiert bis auf weiteren
buchstäblich wie hier aufgenommen werden). Für den Musterabgleich im Glob-Stil dürfen die Glob-Zeichen weder in Literal noch in einer Variablen in Anführungszeichen gesetzt werden : [[ $a == foo* ]]. Können Sie neben meinem Beispiel für eine wörtliche Zeichenfolge weitere Beispiele für eine Anforderung zum Zitieren angeben?
Bis auf weiteres angehalten.

Antworten:

6

Wenn der Wert von $FOOein einzelnes Wort ist, das kein Platzhalterzeichen enthält \[*?, sind die beiden identisch.

Wenn $FOOes nicht zugewiesen oder leer ist oder mehr als ein Wort enthält (dh Leerzeichen oder enthält $IFS), ist die nicht zitierte Version ein Syntaxfehler. Wenn es sich um genau die richtige Folge von Wörtern handelt (z. B. 0 -eq 0 -o false), kann das Ergebnis beliebig sein. Daher empfiehlt es sich, Variablen immer in Shell-Skripten anzugeben.

Muss übrigens "true"nicht zitiert werden.

200_Erfolg
quelle
3

Um zu veranschaulichen, welche Probleme dies verursachen könnte, hier einige Beispiele.

Angenommen, wir haben zwei Variablen wie folgt:

FOO="some value"
BAR="some value"

Jetzt haben wir zwei Variablen, die genau den gleichen String / Wert enthalten. Wenn wir einige if-Anweisungen gemacht haben, um das Ergebnis zu testen, in Ihrem Fall:

if [ $FOO = "$BAR" ]; then echo "match"; else echo "no match"; fi

An diesem Punkt werden Sie bekommen bash: [: too many arguments. Das nicht zitierte $ FOO enthält jetzt drei Werte, nämlich '[ , some , value'. [Das Schlüsselwort test weiß nicht, was ausgeführt werden soll, da erwartet wird, dass das erste oder zweite Argument ein Operator ist.

Wenn wir "$ FOO" zitieren, sagen wir ausdrücklich, dass wir uns ifdie richtigen Werte ansehen sollen, bei denen keine Wortteilung stattfindet.

Ein anderes Beispiel:

my_file="A random file.txt"
  • Tun rm $my_filebedeutet, 'A' 'random' 'file.txt' zu entfernen, wodurch drei Dateien entstehen.
  • rm "$my_file"Wenn Sie dies tun, wird "A random file.txt" entfernt, wodurch eine Datei erstellt wird.

Ich hoffe, ich habe Sie nicht mit diesen Beispielen verwechselt.

Valentin Bajrami
quelle
0

In diesem speziellen Fall gibt es keinen Unterschied.

Wenn Sie jedoch $FOOein Leerzeichen oder einige Sonderzeichen enthalten, liegt ein Problem vor.

In diesem "$FOO"Fall wird die Variable insgesamt verwendet, damit die Übereinstimmung Sie vom Platzproblem isoliert.

Wenn Sie jedoch verwenden $FOOund es einen Sonderfall gibt, wirkt sich dies auf die if-Anweisung aus.

mdpc
quelle