Czy dla wersji Bash wcześniejszych niż „GNU bash, wersja 4.2” istnieją równoważne alternatywy dla -v
opcji test
polecenia? Na przykład:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
-v
nie jest opcjątest
, ale jest operatorem wyrażeń warunkowych.option
do poleceniatest -v
, ANoperator
Doconditional expression
iunary test primary
dla[ ]
. Nie mieszaj języka angielskiego z definicjami powłoki.Odpowiedzi:
Przenośny dla wszystkich powłok POSIX:
Zrób to,
${foobar:+1}
jeśli chcesz traktować wfoobar
ten sam sposób, czy jest pusty, czy nie zdefiniowany. Możesz także użyć,${foobar-}
aby uzyskać pusty ciąg znaków, gdyfoobar
jest niezdefiniowany, i wartość wfoobar
przeciwnym razie (lub wstawić dowolną inną wartość domyślną po-
).W ksh, jeśli
foobar
jest zadeklarowane, ale nie zdefiniowane, jak wtypeset -a foobar
, to${foobar+1}
rozwija się do pustego ciągu.Zsh nie ma zmiennych, które zostały zadeklarowane, ale nie zostały ustawione:
typeset -a foobar
tworzy pustą tablicę.W bash tablice zachowują się w inny i zaskakujący sposób.
${a+1}
rozwija się tylko do1
jeślia
jest niepustą tablicą, npTa sama zasada dotyczy tablic asocjacyjnych: zmienne tablicowe są traktowane jak zdefiniowane, jeśli mają niepusty zbiór indeksów.
Innym, specyficznym dla basha sposobem testowania, czy zmienna dowolnego typu została zdefiniowana, jest sprawdzenie, czy jest wymieniona w . Raportuje puste tablice zgodnie z definicją, w przeciwieństwie do
${!PREFIX*}
${foobar+1}
, ale zgłasza zmienne zadeklarowane, ale nieprzypisane (unset foobar; typeset -a foobar
) jako niezdefiniowane.Jest to równoważne z testowaniem wartości zwracanej
typeset -p foobar
lubdeclare -p foobar
, z tym wyjątkiem, żetypeset -p foobar
zawodzi w przypadku zadeklarowanych, ale nieprzypisanych zmiennych.W bash, podobnie jak w ksh,
set -o nounset; typeset -a foobar; echo $foobar
wyzwala błąd przy próbie rozwinięcia niezdefiniowanej zmiennejfoobar
. W przeciwieństwie do kshset -o nounset; foobar=(); echo $foobar
(lubecho "${foobar[@]}"
) również powoduje błąd.Zauważ, że we wszystkich opisanych tutaj sytuacjach,
${foobar+1}
rozwija się do pustego ciągu, jeśli i tylko jeśli$foobar
spowodowałby błąd podset -o nounset
.źródło
echo "${foobar:+1}"
nie drukuje,1
jeślideclare -a foobar
zostało wcześniej wydane, a zatemfoobar
jest tablicą indeksowaną.declare -p foobar
poprawnie raportujedeclare -a foobar='()'
. Czy działa"${foobar:+1}"
tylko w przypadku zmiennych innych niż tablica?${foobar+1}
(bez:
, odwróciłem dwa przykłady w mojej oryginalnej odpowiedzi) jest poprawny dla tablic w bash, jeśli twoja definicja „zdefiniowanego” brzmi „$foobar
działałabyset -o nounset
”. Jeśli twoja definicja jest inna, bash jest trochę dziwny. Zobacz moją zaktualizowaną odpowiedź.0
indeks, ani klucz nie są zdefiniowane tak, jak są prawdziwea=()
,${a+1}
poprawnie nic nie zwraca.defined
operatora.Test
mógłby to zrobić; to nie może być trudne ( um ....)Podsumowując odpowiedź Gillesa, wymyśliłem następujące zasady:
[[ -v foobar ]]
dla zmiennych w wersji Bash> = 4.2.declare -p foobar &>/dev/null
dla zmiennych tablicowych w wersji Bash <4.2.(( ${foo[0]+1} ))
lub(( ${bar[foo]+1} ))
dla indeksu dolnego odpowiednio tablicy indeksowanej (-a
) i keyed (-A
)declare
. Opcje 1 i 2 nie działają tutaj.źródło
Używam tej samej techniki dla wszystkich zmiennych w bash, i to działa, np .:
wyjścia:
podczas
wyjścia:
źródło
foobar=""
Następnie to zgłosifoobar is unset
. Nie czekaj, cofam to. Naprawdę sprawdza tylko, czy pierwszy element jest pusty, czy nie, więc wydaje się dobrym pomysłem, jeśli wiesz, że zmienna NIE jest tablicą i zależy ci tylko na pustce, a nie na definiowaniu.