Как проверить, что $ 1 и $ 2 равны нулю?

41

Я запускаю некоторый скрипт, который передает строковый аргумент, и я хочу сделать, если оператор else, как показано ниже:

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

но это показано Error too many argument. Зачем?

тайминдис вун
источник
Вы должны предоставить 1. команду, которую вы называете скриптом, и 2. полный вывод.
Лусио
2
Вы должны использовать [[ ]]. В противном случае вы должны указать свои переменные.
Кристоф Де Тройер
Если бы $ 1 не существовало, то $ 2 превратилось бы в $ 1, что делает тест $ 1 и $ 2, оба из которых равны нулю, кажутся неактуальными.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Не обязательно не имеет значения - в некоторых случаях вы хотите убедиться, что в аргументах есть что-то вместо пустой или пустой строки. $1может быть сброшен или установлен на пустую строку пользователем скрипта. Рассмотрим следующую последовательность команд: $ set '' barзатем echo "x${1}x";обе переменные установлены, но одна из них равна нулю.
Сергей Колодяжный

Ответы:

56

Попробуйте использовать тест -z:

if [ -z "$1" ] && [ -z "$2" ]

От мужчины bash:

-z string
   True if the length of string is zero.
Сильвен Пино
источник
Меня устраивает!
pengisgood
Интересно, что наиболее проголосовавший и принятый ответ фактически не отвечает на заданный вопрос.
Мехмет
При написании сценариев переносимой оболочки этот флаг следует использовать с осторожностью, поскольку в некоторых коммерческих Unix-системах этот флаг некорректен. Смотрите мой ответ для связанных источников.
Сергей Колодяжный
3

Следующее также работает,

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi
Авинаш Радж
источник
&&И другие логические команды разделители не допускаются в классический test. Вместо этого вы должны использовать другие тестовые конструкции (например -a, я думаю)
Muru
3

Для старой версии ответа см. Вторую часть этого ответа. Если вы хотите узнать о деталях, читайте дальше

Причина проблемы

В самом вопросе сообщается, что OP видит too many arguments error, что при тестировании bashне выглядит так:

$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected

С /bin/shкоторой на самом деле есть символическая ссылка /bin/dashна Ubuntu, ошибка сообщается следующим образом:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

И автономный /bin/testтакже:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Sidenote: Если вам интересно, что /usr/bin/testи для чего я использую bashи sh, тогда вы должны знать, что [это псевдоним для testкоманды, который также существует как автономный исполняемый файл или чаще - как встроенная оболочка, которую каждая оболочка будет использовать первой. , Что касается ifоператоров, они действуют на состояниях выхода команд, следовательно, почему [и testявляются командами, а все остальное является аргументами этих команд - неправильный порядок этих аргументов командной строки приводит к ошибкам.

Вернемся к теме: неясно, как ОП получил несвязанную ошибку. Однако во всех трех случаях проблема одна и та же - неустановленная переменная будет считаться пустой, поэтому оболочка с этими переменными без кавычек выглядит так:

[ != '' ]

который нарушает синтаксис, который testпонимает. Помните, что я сказал о неправильном порядке аргументов командной строки? Следовательно, почему цитирование важно. Давайте включим диагностический вывод и посмотрим, какая оболочка выполняется:

$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ] 
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars

Лучший способ проверить неустановленные переменные

Очень часто встречающийся подход заключается в следующем:

 if [ "x$var1" == "x"  ] && [ "x$var2" == "x"  ];                                                                
 then
     echo "both variables are null"
 fi

Процитирую Жиля :

В ["x $ 1" = "x"] префикс x гарантирует, что x "$ 1" не может выглядеть как оператор, и поэтому единственный способ, которым оболочка может проанализировать этот тест, - обработать = как бинарный оператор.

Предположительно, это должно быть довольно переносимо, так как я видел это в /bin/shскриптах. Это также может быть объединено как в

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

Конечно, мы могли бы использовать -zфлаг, однако, согласно исследованиям в некоторых оболочках, в частности, ksh88 (согласно Стефану Чазеласу ), этот флаг неисправен.

Смотрите также

Сергей Колодяжный
источник
+1 за очень интересный подход.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Отредактировано, чтобы сделать его еще более интересным :)
Сергей Колодяжный
1

Я думаю, что название поста не является точным, так как в сообщении намеревалось проверить, не равны ли $ 1 и $ 2 значения NULL. В данном примере просто не хватало двойных кавычек в $ 1 и $ 2 для работы. Переменные должны быть заключены в двойные кавычки, чтобы их можно было расширить при сравнении строк. Но проверить, существуют ли $ 1 и $ 2, - это то же самое, что проверить, существуют ли $ 2, поскольку он не может существовать, если $ 1 не существует. Команда 'if' также не требуется в этом случае, так как 'test' возвращает true / false и использует '&&' как 'then', если return равно 0 / true:

[ "$2" != '' ] && commands...

Проще, с -n (отличным от нуля):

[ -n "$2" ] && commands...

«Проверить, равны ли $ 1 и $ 2 нулю», было бы то же самое, что проверить, нет ли параметра:

[ $# -eq 0 ] && commands...
Гуариба сом
источник