Jeśli twój $VARIABLE
jest ciągiem zawierającym spacje lub inne znaki specjalne, a używane są pojedyncze nawiasy kwadratowe (co jest skrótem do test
polecenia), to ciąg może być podzielony na wiele słów. Każdy z nich jest traktowany jako osobny argument.
Tak więc jedna zmienna jest podzielona na wiele argumentów :
VARIABLE=$(/some/command);
# returns "hello world"
if [ $VARIABLE == 0 ]; then
# fails as if you wrote:
# if [ hello world == 0 ]
fi
To samo dotyczy każdego wywołania funkcji, które odkłada ciąg znaków zawierający spacje lub inne znaki specjalne.
Łatwa naprawa
Zawiń dane wyjściowe zmiennej w podwójne cudzysłowy, zmuszając ją do pozostania jako jeden ciąg (a zatem jeden argument). Na przykład,
VARIABLE=$(/some/command);
if [ "$VARIABLE" == 0 ]; then
# some action
fi
Proste. Przejdź jednak do „Uważaj też ...” poniżej, jeśli nie możesz zagwarantować, że zmienna nie będzie ciągiem pustym lub ciągiem znaków, który nie zawiera nic oprócz białych znaków.
Lub alternatywną poprawką jest użycie podwójnych nawiasów kwadratowych (co jest skrótem dla new test
polecenia).
Istnieje to jednak tylko w bash (i najwyraźniej korn i zsh), więc może nie być kompatybilny z domyślnymi powłokami wywoływanymi przez /bin/sh
itp.
Oznacza to, że w niektórych systemach może działać z konsoli, ale nie jest wywoływany gdzie indziej, na przykład zcron
, w zależności od konfiguracji wszystkiego.
Wyglądałoby to tak:
VARIABLE=$(/some/command);
if [[ $VARIABLE == 0 ]]; then
# some action
fi
Jeśli twoje polecenie zawiera podwójne nawiasy kwadratowe i wyświetlasz błędy w logach, ale działa ono z konsoli, spróbuj zamienić [[
alternatywę na sugerowaną tutaj alternatywę lub upewnij się, że cokolwiek uruchamia skrypt używa powłoki obsługującej [[
aka new test
.
Uważaj również na [: unary operator expected
błąd
Jeśli widzisz błąd „zbyt wielu argumentów”, możliwe, że otrzymujesz ciąg znaków z funkcji o nieprzewidywalnym wyniku. Jeśli możliwe jest również uzyskanie pustego łańcucha (lub całego łańcucha spacji), byłoby to traktowane jako zero argumentów, nawet przy powyższej „szybkiej poprawce”, i nie powiodło się[: unary operator expected
To samo „gotcha”, jeśli jesteś przyzwyczajony do innych języków - nie spodziewasz się, że zawartość zmiennej zostanie skutecznie wydrukowana w takim kodzie, zanim zostanie sprawdzona.
Oto przykład, który zapobiega zarówno błędom, jak [: too many arguments
i [: unary operator expected
błędom: zastąpienie wyjścia wartością domyślną, jeśli jest puste (w tym przykładzie, 0
), z podwójnymi cudzysłowami owiniętymi wokół całej rzeczy:
VARIABLE=$(/some/command);
if [ "${VARIABLE:-0}" == 0 ]; then
# some action
fi
(tutaj akcja nastąpi, jeśli $ VARIABLE ma wartość 0 lub jest pusta. Naturalnie, powinieneś zmienić 0 (wartość domyślna) na inną wartość domyślną, jeśli pożądane jest inne zachowanie)
Uwaga końcowa: Ponieważ [
jest to skrót test
, wszystkie powyższe dotyczy również błędu test: too many arguments
(i również test: unary operator expected
)