Poniższy kod kończy działanie z niepowiązanym błędem zmiennej. Jak to naprawić, nadal używając set -oopcji 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 VALUEkończy się jako pusty łańcuch, jeśli WHATEVERnie jest ustawiony. Używamy {parameter:-word}rozszerzenia, które możesz sprawdzić w man bashsekcji „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
$WHATEVERzawiera 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ą
-zsprawdza tylko, czy następny parametr jest pusty. -zjest tylko argumentem [polecenia. Zmienna ekspansja ma miejsce, zanim [ -zcokolwiek 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 -nlub -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 nounsetto, co jest specyficzne dla basha. Jeśli umieścisz znak #!/bin/bashna 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.