Poniższy kod kończy działanie z niepowiązanym błędem zmiennej. Jak to naprawić, nadal używając set -o
opcji rzeczownika?
#!/bin/bash
set -o nounset
if [ ! -z ${WHATEVER} ];
then echo "yo"
fi
echo "whatever"
Odpowiedzi:
#!/bin/bash
set -o nounset
VALUE=${WHATEVER:-}
if [ ! -z ${VALUE} ];
then echo "yo"
fi
echo "whatever"
W tym przypadku VALUE
kończy się jako pusty łańcuch, jeśli WHATEVER
nie jest ustawiony. Używamy {parameter:-word}
rozszerzenia, które możesz sprawdzić w man bash
sekcji „Rozszerzenie parametrów”.
:-
sprawdza, czy zmienna jest nieustawiona lub pusta. Jeśli chcesz sprawdzić tylko , czy jest wyłączony, należy -
: VALUE=${WHATEVER-}
. Ponadto czytelniejszy sposób sprawdzenia, czy zmienna jest pusta:if [ "${WHATEVER+defined}" = defined ]; then echo defined; else echo undefined; fi
$WHATEVER
zawiera tylko spacje - Zobacz moją odpowiedź.
! -z
” zamiast tylko „ -n
”?
Musisz zacytować zmienne, jeśli chcesz uzyskać oczekiwany wynik:
check() {
if [ -n "${WHATEVER-}" ]
then
echo 'not empty'
elif [ "${WHATEVER+defined}" = defined ]
then
echo 'empty but defined'
else
echo 'unset'
fi
}
Test:
$ unset WHATEVER
$ check
unset
$ WHATEVER=
$ check
empty but defined
$ WHATEVER=' '
$ check
not empty
"info bash"
, "${WHATEVER-}"
powinien mieć ":"
(dwukropek) przed "-"
(myślnik), takich jak: "${WHATEVER:-}"
i "${WHATEVER+defined}"
powinien mieć dwukropek przed "+"
(plus), takich jak: "${WHATEVER:+defined}"
. U mnie działa to w obie strony, z okrężnicą lub bez. W niektórych wersjach 'nix prawdopodobnie nie zadziała bez uwzględnienia dwukropka, więc prawdopodobnie powinno zostać dodane.
-
, +
, :+
, i :-
są obsługiwane. Pierwsza wykrywa, czy zmienna jest ustawiona , a druga, czy jest ustawiona, czy pusta . Od man bash
: „Pominięcie dwukropka powoduje test tylko dla nieustawionego parametru”.
A może oneliner?
[ -z "${VAR:-}" ] && echo "VAR is not set or is empty" || echo "VAR is set to $VAR"
-z
sprawdza zarówno pustą, jak i nieustawioną zmienną
-z
sprawdza tylko, czy następny parametr jest pusty. -z
jest tylko argumentem [
polecenia. Zmienna ekspansja ma miejsce, zanim [ -z
cokolwiek zrobi.
Założenia:
$ echo $SHELL
/bin/bash
$ /bin/bash --version | head -1
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
$ set -o nounset
Jeśli chcesz, aby nieinteraktywny skrypt wyświetlał błąd i kończył pracę, jeśli zmienna ma wartość null lub nie jest ustawiona:
$ [[ "${HOME:?}" ]]
$ [[ "${IAMUNBOUND:?}" ]]
bash: IAMUNBOUND: parameter null or not set
$ IAMNULL=""
$ [[ "${IAMNULL:?}" ]]
bash: IAMNULL: parameter null or not set
Jeśli nie chcesz, aby skrypt kończył się:
$ [[ "${HOME:-}" ]] || echo "Parameter null or not set."
$ [[ "${IAMUNBOUND:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.
$ IAMNULL=""
$ [[ "${IAMUNNULL:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.
Możesz nawet użyć [
i ]
zamiast [[
i ]]
powyżej, ale ten drugi jest lepszy w Bash.
Zwróć uwagę, co robi dwukropek powyżej. Z dokumentów :
Innymi słowy, jeśli uwzględniono dwukropek, operator sprawdza istnienie obu parametrów i czy ich wartość nie jest zerowa; jeśli dwukropek zostanie pominięty, operator sprawdza tylko istnienie.
Najwyraźniej nie ma potrzeby -n
lub -z
.
Podsumowując, zwykle mogę po prostu użyć [[ "${VAR:?}" ]]
. Zgodnie z przykładami, to wyświetla błąd i kończy działanie, jeśli zmienna ma wartość null lub nie jest ustawiona.
Możesz użyć
if [[ ${WHATEVER:+$WHATEVER} ]]; then
ale
if [[ "${WHATEVER:+isset}" == "isset" ]]; then
może być bardziej czytelny.
=
operatora standardowego (POSIX) , a nie w ==
celu ułatwienia przenoszenia, a [
zamiast tego, [[
jeśli to możliwe.
set -o nounset
to, co jest specyficzne dla basha. Jeśli umieścisz znak #!/bin/bash
na górze swojego skryptu, najlepiej jest użyć ulepszeń basha.
Chociaż nie jest to dokładnie ten przypadek użycia, o który pytano powyżej, odkryłem, że jeśli chcesz użyć nounset
(lub -u
), domyślne zachowanie jest takie, jakie chcesz: wyjście niezerowe z komunikatem opisowym.
Zajęło mi wystarczająco dużo czasu, zanim zdałem sobie z tego sprawę, i pomyślałem, że warto go opublikować jako rozwiązanie.
Jeśli chcesz tylko powtórzyć coś innego podczas wychodzenia lub wykonać jakieś czyszczenie, możesz użyć pułapki.
W :-
przeciwnym razie operator jest prawdopodobnie tym, czego chcesz.