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.


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.


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.


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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.