Warum haben [[-z]] und [[-v]] unterschiedliche Syntax?

8

Wenn ich einige Befehle ausführen möchte, deren Variablen nicht festgelegt sind, verwende ich:

if [[ -z "$a" || -z "$v" ]]
then
  echo "a or b are not set"
fi

Die gleiche Syntax funktioniert jedoch nicht -v. Ich muss Folgendes verwenden:

if [[ -v a && -v b ]]
then
  echo "a & b are set"
fi

Was ist die Geschichte dahinter? Ich verstehe nicht, warum die Syntax nicht dieselbe sein würde. Ich habe gelesen, dass dies -veine etwas neue Ergänzung zu Bash (4.2) ist .

Philip Kirkbride
quelle
Was ist die Frage? Fragen Sie, warum Sie das Dollarzeichen verwenden müssen?
Choroba
Eine Variable kann auf""
Kevin

Antworten:

21

Testoperatoren -vund -zsind einfach nicht gleich.

Der Operator gibt an -z, ob eine Zeichenfolge leer ist. Es ist also wahr, dass [[ -z "$a" ]]sich eine gute Annäherung an "Variable aist nicht gesetzt" ergibt, aber keine perfekte:

  • Der Ausdruck ergibt true, wenn er aauf die leere Zeichenfolge gesetzt und nicht auf den Wert gesetzt ist.

  • Das beiliegende Skript schlägt fehl, wenn aes nicht festgelegt ist und die Option nounsetaktiviert ist.

Auf der anderen Seite -v awird genau "Variable agesetzt" sein, auch in Randfällen. Es sollte klar sein , dass vorbei , $aanstatt azu -vwäre nicht richtig, da es , dass möglicherweise-unset Variable erweitern würde , bevor der Test Operator es sieht; Daher muss es Teil der Aufgabe dieses Operators sein, diese Variable, auf die der Name zeigt, zu überprüfen und festzustellen, ob sie festgelegt ist.

dhag
quelle
Wenn Sie Edge Case sagen, meinen Sie damit, dass sie unterschiedlich leer sind? Zum Beispiel a=""?
Philip Kirkbride
Ja, genau das meine ich.
Dhag
3
Beachten Sie, dass es auch Randfälle für gibt [[ -v ]]. Gibt wie bei einem variablen Array- Typ [[ -v var ]]nur dann true zurück, wenn ${var[0]}(praktisch wie $var) festgelegt ist. Auch für assoziatives Array ${var[0]}(nicht ${var[00]}zum Beispiel). [[ -v var[@] ]]würde true zurückgeben, wenn für das Array ein Wert festgelegt ist (würde false für eine Variable zurückgeben, die als festgelegt ist var=()). Das liegt an der verrückten Art und Weise, wie Variablen in ksh / bash eingegeben werden. Siehe zshfür eine weniger verwirrende Variablentypisierung.
Stéphane Chazelas
Ah, guter Punkt. Sie haben bemerkt, dass ich vorsichtig nicht auf das Array-Problem eingegangen bin :).
Dhag
2
Genauer gesagt: -zTestet einen Wert, während -aein Name getestet wird .
Chepner
7

Es gibt einen Unterschied in der Bedeutung von -zund -v:

echo Empty:
x=""  # Same with x=
[[ -z $x ]] && echo z
[[ -v  x ]] && echo v
unset x

echo Unset
[[ -z $x ]] && echo z
[[ -v  x ]] && echo v

Mit -zkönnen Sie eine Variable, der ein leerer Wert zugewiesen wurde, nicht von einer Variablen unterscheiden, der kein Wert zugewiesen wurde.

Auch [[ -z $x ]]ist noch sinnvoll set -u, während [[ -v x ]]nicht.

Choroba
quelle