Gibt es für Bash-Versionen vor "GNU bash, Version 4.2" gleichwertige Alternativen für die -v
Option des test
Befehls? Beispielsweise:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
-v
ist keine Option fürtest
, sondern ein Operator für bedingte Ausdrücke.option
auf einen Befehltest -v
, eineoperator
auf einconditional expression
undunary test primary
für[ ]
. Mischen Sie nicht die englische Sprache mit Shell-Definitionen.Antworten:
Portabel auf alle POSIX-Shells:
Machen Sie das,
${foobar:+1}
wenn Sie gleich behandeln möchten,foobar
ob es leer oder nicht definiert ist. Sie können auch verwenden${foobar-}
, um eine leere Zeichenfolge abzurufen, wennfoobar
undefiniert und der Wert von "foobar
else" (oder einen anderen Standardwert nach "-
).In KSH, wenn
foobar
erklärt wird , aber nicht definiert, wie intypeset -a foobar
, dann${foobar+1}
auf die leere Zeichenfolge erweitert.Zsh hat keine deklarierten, aber nicht gesetzten Variablen: Erstellt
typeset -a foobar
ein leeres Array.In bash verhalten sich Arrays anders und überraschend.
${a+1}
wird nur erweitert,1
wenna
es sich um ein nicht leeres Array handelt, zDasselbe Prinzip gilt für assoziative Arrays: Array-Variablen werden wie definiert behandelt, wenn sie eine nicht leere Menge von Indizes enthalten.
Eine andere, bash-spezifische Methode zum Testen, ob eine Variable eines beliebigen Typs definiert wurde, besteht darin, zu überprüfen, ob sie in aufgeführt ist . Dies meldet leere Arrays als definiert, im Gegensatz zu deklarierten aber nicht zugewiesenen Variablen ( ) jedoch als undefiniert.
${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
Dies entspricht dem Testen des Rückgabewerts von
typeset -p foobar
oderdeclare -p foobar
, mit der Ausnahme, dasstypeset -p foobar
bei deklarierten, aber nicht zugewiesenen Variablen ein Fehler auftritt.In bash wird wie in ksh
set -o nounset; typeset -a foobar; echo $foobar
beim Versuch, die undefinierte Variable zu erweitern , ein Fehler ausgelöstfoobar
. Anders als in ksh löstset -o nounset; foobar=(); echo $foobar
(oderecho "${foobar[@]}"
) auch einen Fehler aus.Beachten Sie, dass in allen hier beschriebenen Situationen
${foobar+1}
nur dann$foobar
eine Erweiterung auf die leere Zeichenfolge erfolgt, wenn dies zu einem Fehler unter führen würdeset -o nounset
.quelle
echo "${foobar:+1}"
wird nicht gedruckt,1
wenn siedeclare -a foobar
zuvor ausgegeben wurde, undfoobar
ist daher ein indiziertes Array.declare -p foobar
richtig berichtetdeclare -a foobar='()'
. Funktioniert"${foobar:+1}"
nur für Nicht-Array-Variablen?${foobar+1}
(ohne das:
, ich habe zwei Beispiele in meiner ursprünglichen Antwort invertiert) ist für Arrays in bash korrekt, wenn Ihre Definition von "defined" "would$foobar
work underset -o nounset
" lautet . Wenn Ihre Definition anders ist, ist bash ein bisschen komisch. Siehe meine aktualisierte Antwort.0
Index noch ein Schlüssel als wahr definiert sinda=()
,${a+1}
wird nichts korrekt zurückgegeben.defined
Operator.Test
könnte das tun; es kann nicht schwierig sein ( ähm ...)Um mit Gilles 'Antwort zusammenzufassen, habe ich folgende Regeln aufgestellt:
[[ -v foobar ]]
für Variablen in der Bash-Version> = 4.2.declare -p foobar &>/dev/null
für Array-Variablen in Bash-Version <4.2.(( ${foo[0]+1} ))
bzw.(( ${bar[foo]+1} ))
für Indizes von indizierten (-a
) und verschlüsselten (-A
) Arrays (declare
). Option 1 und 2 funktionieren hier nicht.quelle
Ich verwende die gleiche Technik für alle Variablen in Bash, und es funktioniert, zB:
Ausgänge:
während
Ausgänge:
quelle
foobar=""
werde das dann meldenfoobar is unset
. Nein, ich nehme das zurück. Tatsächlich wird nur geprüft, ob das erste Element leer ist oder nicht. Daher ist es nur eine gute Idee, wenn Sie wissen, dass die Variable KEIN Array ist und Sie sich nur um die Leere und nicht um die Definiertheit kümmern.