Сравнить целое число в bash, ожидается унарный оператор

137

Следующий код дает

[: -ge: ожидается унарный оператор

когда

i=0

if [ $i -ge 2 ]
then
    #some code
fi

Зачем?

Филип Экберг
источник

Ответы:

295

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

if [ "$i" -ge 2 ] ; then
  ...
fi

Это связано с тем, как оболочка обрабатывает переменные. Предположим исходный пример,

if [ $i -ge 2 ] ; then ...

Первое, что делает оболочка при выполнении этой конкретной строки кода, - это подставляет значение $i, как это сделала бы функция поиска и замены вашего любимого редактора . Итак, предположим, что $iэто пусто, или, что еще более наглядно, предположим, что $iэто куча пробелов! Оболочка заменит $iследующим образом:

if [     -ge 2 ] ; then ...

Теперь, когда подстановки переменных выполнены, оболочка продолжает сравнение и ... терпит неудачу, потому что не видит ничего понятного слева от -gt. Однако цитируя $i:

if [ "$i" -ge 2 ] ; then ...

становится:

if [ "    " -ge 2 ] ; then ...

Теперь оболочка видит двойные кавычки и знает, что вы на самом деле сравниваете четыре пробела с двумя и пропускаете if.

У вас также есть возможность указать значение по умолчанию для $iif $iis blank, как показано ниже:

if [ "${i:-0}" -ge 2 ] ; then ...

Это будет подставить значение 0 вместо того , чтобы $iэто $iне определено. Я все еще сохраняю кавычки, потому что, опять же, если $iэто куча пробелов, то они не считаются неопределенными , они не будут заменены на 0, и вы снова столкнетесь с проблемой.

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

владр
источник
7
цитирование переменной вызовет новую ошибку, например, ожидаемое целочисленное выражение
Нестор
@ Néstor неверно , цитирование переменной НЕ вызовет новой ошибки, такой как целочисленное выражение, ожидаемое, если переменная является числовой; предоставление значения нечисловой переменной, независимо от того, заключено ли оно в кавычки, приведет к указанной ошибке.
vladr
6

Судя по сообщению об ошибке, значение i было пустой строкой, когда вы ее выполнили, а не 0.

звездно-голубой
источник
6

Мне нужно добавить свои 5 центов. Я вижу, что все используют [или [[, но стоит отметить, что они не являются частью синтаксиса if.

((...))Вместо этого используйте для арифметических сравнений .

((...)) - это арифметическая команда, которая возвращает статус выхода 0, если выражение не равно нулю, или 1, если выражение равно нулю. Также используется как синоним «let», если необходимы побочные эффекты (назначения).

См .: ArithmeticExpression

Роман Ньюаза
источник
2

Ваш сценарий отлично работает. Вы уверены, что не назначаете что-либо еще до «i»?

Распространенной ошибкой также является не оставлять пробелов после квадратных скобок и перед ними.

Фернандо Мигелес
источник