На самом деле можно установить некоторые атрибуты на переменных с помощью declare
(или старое typeset
) встроенный. declare -i var1 var2
установит целочисленный атрибут на тех переменных. После этого присвоения, которые пытаются установить значения нецелого числа к тем переменным, повысят ошибку.
Но Ваша проблема с синтаксисом. При использовании значения переменной необходимо снабдить префиксом его имя $
:
if [ "$var1" -lt "$var2" ]; then
echo "$var1 is lt $var2"
else
echo "$var2 is lt $var1"
fi
Исключениями являются арифметические оценки, где никакая потребность не для $
:
if ((var1<var2)); then
echo "$var1 is lt $var2"
else
echo "$var2 is lt $var1"
fi
Как слово предупреждения, внутри [
..]
всегда двойная кавычка Ваши переменные для предотвращения расширения слова, портящего синтаксис выражения. (Я имею в виду, у Вас будут проблемы с переменными сброса, переменные, содержащие пустую строку и переменные, содержащие IFS
символы.) Или можно использовать более новое и лучшее [[
..]]
вместо этого, который обрабатывает такие случаи правильно:
if [[ $var1 -lt $var2 ]]; then
echo "$var1 is lt $var2"
else
echo "$var2 is lt $var1"
fi
Из руководства:
Переменная оболочки, которая является пустой или сброс, оценивает к 0 при ссылке по имени, не используя синтаксис расширения параметра.
Я не знаю об этом изменявшемся, и это также имеет место в pdksh, ksh93, тире и zsh, но POSIX не указывает поведение.
Отметьте это если set -o nounset
(иначе. set -u
) в действительности, $((a))
или ((a+=1))
вызывает ошибку если a
сброшен (в ударе и ksh93, но не в тире, pdksh или zsh).
Обратите внимание также, что это только применяется при использовании параметра непосредственно в арифметическом выражении $((a+1))
, не, когда Вы используете замену параметра $(($a+1))
. Контраст:
$ unset a
$ echo $((1 - a + 2)) # 1 - 0 + 2
3
$ echo $((a - $a + 2)) # 1 - (+2)
-1
Да, bash
арифметическое расширение одолжено от ksh
, и это было зарегистрированным путем в ksh
с 80-х.
Отметьте однако, это в расширении арифметики POSIX как в $((x * 2))
, поведение является неуказанным (POSIX) если $x
содержит десятичную числовую константу (как в, 2
и -2
в порядке, но пустая строка или 1+1
не), что означает, что Вы не можете сделать то предположение в POSIX sh
сценарии.
Также остерегайтесь (в bash
, ksh
, zsh
по крайней мере):
$ echo $((2*$foo-2)) # actually $((2*-2))
-4
$ echo $((2*foo-2)) # actually $((2*0-2))
-2
Вероятно, безопасно предположить, что удар заменит пустыми переменными с 0 в любой довольно недавней системе.
Поскольку это документируется в страницу справочника для удара 4.2, это - конечно, зарегистрированное поведение, по крайней мере, с той версии. Как это описано как поведение тот путь (но недокументированное) в Усовершенствованном Руководстве по созданию сценариев Bash, можно ожидать, что поведение в любой версии удара было доступно, когда это было записано. Это, вероятно, возвращается к очень ранним версиям удара.
Если Вы захотите быть АБСОЛЮТНО строгими, однако, то необходимо будет проверить документацию на все версии удара, которые Вы хотите поддерживать, и Вы не можете сделать предположения ни об одной из тех версий, которые явно не документируют поведение.
Я не думаю, что необходимо быть абсолютно строгими, но если Вы не рискуете, можно использовать foo=${foo:-0}
явно установить неопределенные переменные на 0 перед использованием их. Пример:
foo=1
foo=${foo:-0}
bar=${bar:-0}
echo "before math: foo=$foo, bar=$bar"
let 'foo += 2'
let 'bar += 2'
echo "after math: foo=$foo, bar=$bar"
Вывод:
before math: foo=1, bar=0
after math: foo=3, bar=2