Конструкции ((…)) и [[…]]
Конструкция ((…)) позволяет работать с целыми числами:
$ 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, если выражение истинно.