Конструкции ((…)) и [[…]]
Конструкция ((…))
позволяет работать с целыми числами:
$ var=$(( 10 + 5 )) $ echo $var 15 $ (( var = var + 1 )) # внутри ((…)) переменные можно использовать без знака $ … $ echo $var 16 $ echo $(( $var * 2 )) # … но можно и со знаком $ 32
Умеет работать с логическими операторами:
$ var=50 $ result=$(( var >= 0 && var <= 100 )) # результат вычисления выражения $ echo $result 1 $ result=$(( var >= 0 && var <= 10 )) # результат вычисления выражения $ echo $result 0
Результат кажется странным, но в первом случае это единица (истина), а во втором случае ноль (ложь). Но при этом код возврата в первом случае будет ноль (истина), а код возврата во втором случае будет единица (ложь).
Так сложилось исторически в shell-скриптах. Если программа выполнилась успешно, она возвращает ноль. Если при выполнении возникли ошибки — программа возвращает код ошибки. Просто не надо путать код возврата и результат вычисления.
Внутри конструкции ((…))
все работает, как в языке програмирования C. Если логический результат ложь — это ноль, если логический результат истина — это единица. Мы используем конструкцию $((…))
, чтобы получить этот результат.
$ var=50 $ (( var >= 0 && var <= 100 )) # код возврата конструкции ((...)) $ echo $? 0 $ (( var >= 0 && var <= 10 )) # код возврата конструкции ((...)) $ echo $? 1
Ее часто используют в операторе if
, когда одновременно нужна работа с целыми числами + есть логические выражения. Если результат логического выражения будет «истина» — код возврата будет нулевым, для if
это означает «истина»:
if ((var == x * 3 + y * 2)) ; then
echo "yes"
fi
Для группировки элементов можно использовать круглые скобки:
$ echo $(( i = (i + 10) * j )) # внутри ((…)) можно использовать пробелы перед и после =
Таким образом, конструкция ((…))
поддерживает:
- операторы сравнения
==
,!=
,>
,<
,>=
,<=
- математические операции
+
,-
,*
,/
,**
,%
- логические операторы
&&
,||
,!
- круглые скобки
(…)
Как и в случае с ((…))
, конструкция [[…]]
позволяет использовать более естественный синтаксис для проверки файлов и сравнения строк. Можно использовать &&
, ||
, <
и >
и круглые скобки (…)
для группировки элементов:
$ [[ ( -d "$HOME" ) && ( -w "$HOME" ) ]] && echo "home is a writable directory"
Операторы <
и >
используются для сравнения строк, а не чисел. Для сравнения чисел надо использовать ((…))
, например ((foo > 7))
.
Можно сказать, что конструкция [[…]]
является расширенной версией команды test
: она умеет делать все то же самое + позволяет использовать &&
, ||
и круглые скобки (…)
без обратных слэшей.
Кроме того, конструкция [[…]]
поддерживает регулярные выражения:
[[ string =~ pattern ]]
Статус выхода устанавливается в 0, если регулярное выражение совпало со строкой, и в 1 — если не совпало. Значение подвыражения, заключённого в скобки, можно получить через переменную BASH_REMATCH[@]
, например:
REGEXP='foo(bar)bl(.*)'
if [[ "abcfoobarbletch" =~ $REGEXP ]] ; then
echo "Регулярное выражение совпало со строкой!"
echo "$BASH_REMATCH" # выводит: foobarbletch
echo "${BASH_REMATCH[@]}" # выводит: foobarbletch bar etch
echo "${BASH_REMATCH[1]}" # выводит: bar
echo "${BASH_REMATCH[2]}" # выводит: etch
fi
Обратите внимание, что внутри [[…]]
регулярное выражение не должно заключаться в кавычки. Если регулярное выражение содержит пробелы, то нужно поместить его в переменную, как сделано в примере выше.
((…))
, конструкция [[…]]
оценивает выражение и устанавливает статус выдачи равный 1, если выражение ложно, или статус выдачи равный 0, если выражение истинно.