W przypadku starej wersji odpowiedzi zobacz drugą część tej odpowiedzi. Jeśli chcesz wiedzieć o szczegółach, czytaj dalej
Przyczyna problemu
W samym pytaniu podano, że OP widzi too many arguments error
, co bash
nie wydaje się , gdy jest testowane :
$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected
Z /bin/sh
którym w rzeczywistości jest symlinkowany /bin/dash
na Ubuntu, błąd zgłaszany w następujący sposób:
$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator
A samodzielny /bin/test
również:
$ /usr/bin/test $1 != ''
/usr/bin/test: missing argument after ‘’
Sidenote: Jeśli zastanawiasz się, co to jest /usr/bin/test
i dlaczego używam bash
i sh
, to powinniście wiedzieć, że [
jest alias dla test
komendy, która występuje także jako samodzielny plik wykonywalny lub częściej - jak skorupy wbudowany w którym to, co każda powłoka użyje pierwszy . Jeśli chodzi o if
instrukcje, operują one na statusach wyjściowych poleceń, stąd polecenia [
i test
są, a wszystko inne jest argumentem tych poleceń - niewłaściwa kolejność tych argumentów wiersza poleceń prowadzi do błędów.
Powrót do tematu: nie jest jasne, w jaki sposób OP otrzymał niepowiązany błąd. Jednak we wszystkich 3 przypadkach problem jest taki sam - zmienna nieuzbrojona będzie traktowana jako pusta, dlatego to, co powłoka widzi z tymi niecytowanymi zmiennymi, to
[ != '' ]
który łamie składnię, która test
rozumie. Pamiętasz, co powiedziałem o niewłaściwej kolejności argumentów wiersza poleceń? Dlatego dlaczego cytowanie jest ważne. Włączmy dane diagnostyczne i zobaczmy, co wykonuje powłoka:
$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ]
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars
Lepszy sposób testowania nieuzbrojonych zmiennych
Bardzo częstym podejściem jest:
if [ "x$var1" == "x" ] && [ "x$var2" == "x" ];
then
echo "both variables are null"
fi
Cytując Gillesa :
W ["x $ 1" = "x"] przedrostek x zapewnia, że x "$ 1" nie może wyglądać jak operator, więc jedynym sposobem, w jaki powłoka może przeanalizować ten test, jest traktowanie = jako operatora binarnego.
Prawdopodobnie powinno to być dość przenośne, ponieważ widziałem je w /bin/sh
skryptach. Można go również łączyć jak w
if [ "x${var1}${var2}" == "x" ]; then
...
fi
Oczywiście moglibyśmy użyć -z
flagi, jednak według badań niektórych pocisków, szczególnie ksh88 (według Stephane Chazelas ), flaga ta jest wadliwa.
Zobacz też