Сценарий оболочки обычно должен проверить, выполняется ли команда успешно или выполняется условие. В Bash этот тест можно выполнить с помощью инструкции if в Bash. Как и в любом другом языке программирования, Bash поставляется с условными выражениями, которые позволяют вам проверять условия и изменять поток управления, если условие выполняется или нет.
В этом посте рассматривается оператор if в bash и связанные с ним предложения then, else if (elif) и else.
В программировании оператор if — это условный оператор, также известный как условное выражение. Оператор if выполнит часть кода, если выполняется заданное условие. На него часто ссылаются как на оператор If-Then, If-Else или If-Then-Else. Оператор if всегда проверяет наличие логического условия для вычисления в true или false. Then, else if (elif) и else являются предложениями к оператору if.
В Bash оператор if является частью условных конструкций языка программирования. if в сценарии Bash — это ключевое слово оболочки Bash, которое используется для тестирования условий на основе состояния завершения тестовой команды. Нулевой статус завершения, и только нулевой, является успешным, то есть условием, которое является истинным. Любой другой статус завершения — это сбой, то есть условие, которое является ложным.
Синтаксис оператора if в Bash таков:
if first-test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
Тестовые команды в инструкции if и предложениях elif выполняются по порядку, пока один тест не завершится успешно. Если ни один тест не завершается успешно, и предоставляется предложение else, то будет выполнена часть кода последнего предложения else.
Конструкции ((…)), […] и [[…]] часто используются для вычисления сложных условных выражений с помощью операторов сравнения и для возврата статуса завершения 0 или 1, который может быть использован в операторе if в bash.
Двойные круглые скобки ((…)) используются для проверки арифметического выражения. Вы можете прочитать больше об этой конструкции в нашем посте об арифметике bash. Он поддерживает двоичные операторы && и ||.
В одиночных квадратных скобках […] указана команда [, которая является встроенной оболочкой и псевдонимом команды test. Команда test и псевдоним [ используются для вычисления условных выражений. Это часть стандарта POSIX.
Существуют некоторые заметные различия между обозначениями в двойных и одинарных скобках:
Двойные квадратные скобки [[…]] — это ключевое слово оболочки. Оно похоже по поведению на одинарную квадратную скобку и используется для вычисления условных выражений и специфично для оболочек Bash, Zsh и Korn. Эта конструкция может обрабатывать более сложные условия и менее подвержена ошибкам.
Обратите внимание, что конструкции ((…)) и [[…]] являются составными командами Bash.
Условные выражения используются [[ составной командой и test и [ встроенными командами. Условные выражения могут быть унарными (один операнд) или двоичными (два операнда). Унарные операторы часто используются для проверки состояния файла, переменной, параметра оболочки (optname) или строки.
Унарные и двоичные выражения формируются со следующими первичными символами.
Условное выражение | Значение |
---|---|
-a file | Верно, если file существует. |
-b file | True if file существует и является специальным файлом для блоков. |
-c file | Верно, если file существует и является файлом со специальным символом. |
-d file | Верно, если file существует и является каталогом. |
-e file | Верно, если file существует. |
-f file | Верно, если file существует и является обычным файлом. |
-g file | Верно, если file существует и установлен бит set-group-id для него. |
-h file | True if file существует и является символической ссылкой. |
-k file | True, если file существует и установлен его бит “sticky”. |
-p file | True, если file существует и является именованным каналом (FIFO). |
-r file | True, если file существует и доступен для чтения. |
-s file | True, если file существует и имеет размер больше нуля. |
-t fd | True, если дескриптор fd file открыт и ссылается на терминал. |
-u file | True, если file существует и установлен бит его идентификатора set-user-id. |
-w file | True, если file существует и доступен для записи. |
-x file | True, если file существует и является исполняемым. |
-G file | True, если file существует и принадлежит действующему идентификатору группы. |
-L file | True, если file существует и является символической ссылкой. |
-N file | True, если file существует и был изменен с момента его последнего чтения. |
-O file | True, если file существует и принадлежит действительному идентификатору пользователя. |
-S file | True, если file существует и является сокетом. |
file1 -ef file2 | Верно, если file1 и file2 относятся к одному и тому же устройству и номерам индексов. |
file1 -nt file2 | True, если file1 новее (в соответствии с датой модификации), чем file2, или если file1 существует, а file2 — нет. |
файл1 -ot файл2 | Верно, если file1 старше, чем file2, или если file2 существует, а file1 нет. |
-o optname | True, если включена опция оболочки optname (список опций см. set -o ). |
-v varname | True, если установлена переменная оболочки varname (было присвоено значение, даже пустое значение). |
-R varname | True, если переменная оболочки varname установлена и является ссылкой на имя. |
-z string | True, если длина string равна нулю. |
-n string | True, если длина string отлична от нуля. |
string1 == string2 string1 = string2 | True, если строки равны. Он будет выполнять сопоставление с шаблоном при использовании с командой [[ . =Обозначения должны использоваться с командой test для соответствия POSIX. |
string1 != string2 | True, если строки не равны. |
string1 =~ regex | True, если строки соответствуют Bash регулярному выражению regex. Захваченные группы хранятся в переменной массива BASH_REMATCH. |
string1 < string2 | True if string1 сортируется перед string2 лексикографически. |
string1 > string2 | True if string1 сортируется после string2 лексикографически. |
Условные выражения также поддерживают арифметические двоичные операторы следующим образом, и где arg1 и arg2 являются либо положительными, либо отрицательными целыми числами. При использовании с командой [[ arg1 и arg2 вычисляются как арифметические выражения, следовательно, следует предпочесть составную команду ((.
Условное выражение | Значение |
---|---|
arg1 -eq arg2 | Верно, если arg1 равен arg2 |
arg1 -ne arg2 | True, если arg1 не равен arg2 |
arg1 -lt arg2 | True, если arg1 меньше, чем arg2 |
arg1 -le arg2 | True, если arg1 меньше или равен arg2 |
arg1 -gt arg2 | True, если arg1 больше, чем arg2 |
arg1 -ge arg2 | True, если arg1 больше или равно arg2 |
Как мы упоминали ранее, оператор If должен содержать предложение then и необязательно может содержать предложение else if с ключевым словом elif, за которым следует then, и/или предложение else. Оператор If всегда заканчивается ключевым словом fi.
Ключевые слова if, then, else, elif и fi должны быть последними ключевыми словами строки, иначе они должны заканчиваться точкой с запятой ; перед использованием любого другого ключевого слова.
if false; then echo 'This command will never run since condition is always false.'; elif ((RANDOM%2)); then echo 'This command will execute only when $RANDOM % 2 equal to 0.'; else echo 'This command will execute if no other condition is met.'; fi
Обратите внимание, что для условия не требуются какие-либо специальные заключающие символы, такие как круглые скобки, хотя они могут использоваться для переопределения приоритета других операторов. В зависимости от выполняемого теста команда может быть использована напрямую, или с помощью [[ составной команды, или с помощью встроенных команд test и [. Составная команда (( зарезервирована для арифметического расширения. Пробелы между ключевыми словами и командами имеют значение.
Например, если мы хотим проверить, существует ли файл и является ли он обычным файлом (не символической ссылкой), мы могли бы использовать -f с любым из следующих обозначений.
[andreyex@linux ~]$ touch myfile [andreyex@linux ~]$ if [[ -f myfile ]]; then echo "myfile exists. If Statement Condition equal $?."; fi myfile exists. If Statement Condition equal 0. [andreyex@linux ~]$ if [ -f myfile ]; then echo "myfile exists. If Statement Condition equal $?."; fi myfile exists. If Statement Condition equal 0. [andreyex@linux ~]$ if test -f myfile; then echo "myfile exists. If Statement Condition equal $?."; fi myfile exists. If Statement Condition equal 0.
Вы можете отменить условие, используя ключевое слово !.
[andreyex@linux ~]$ rm myfile [andreyex@linux ~]$ if [[ ! -f myfile ]]; then echo "myfile does not exist. If Statement Condition equal $?."; fi myfile does not exist. If Statement Condition equal 0.
Как мы упоминали выше, вы можете использовать двоичные операторы && (и) и || (или) в составных обозначениях в двойных скобках [[. Это похоже на использование -a (и) и -o (или) в одной скобке.
[andreyex@linux ~]$ touch myfile [andreyex@linux ~]$ if [[ -f myfile && -r myfile ]]; then echo "File exists and is Readable."; fi File exists and is Readable. [andreyex@linux ~]$ if [ -f myfile -a -r myfile ]; then echo "File exists and is Readable."; fi File exists and is Readable.
[andreyex@linux ~]$ if [ -f myfile && -r myfile ]; then echo "File exists and is Readable."; fi bash: [: missing `]' [andreyex@linux ~]$ if [ -f myfile ] && [ -r myfile ]; then echo "File exists and is Readable."; fi File exists and is Readable. [andreyex@linux ~]$ if test -f myfile && -r myfile; then echo "File exists and is Readable."; fi bash: -r: command not found [andreyex@linux ~]$ if test -f myfile && test -r myfile; then echo "File exists and is Readable."; fi File exists and is Readable.
Вложенный оператор if — это оператор if внутри предложения другого оператора if. Ничто не препятствует использованию нескольких уровней оператора if в сценарии оболочки и в Bash.
if first-test-commands; then if second-level-test-commands; then consequent-commands; else second-level-alternate-consequents; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
Одна из наиболее распространенных ошибок, связанных с командой командной оболочки [, заключается в неправильном использовании кавычек в условном выражении. Строковые литералы не обязательно заключать в кавычки с условием [ or test, если только они не содержат подстановочных знаков.
Первый аргумент условия должен быть заключен в кавычки, если он является переменной. При неправильном использовании вы столкнетесь с ошибкой bash bash: [: too many arguments.
[andreyex@linux ~]$ myVar="a b" # НЕПРАВИЛЬНО [andreyex@linux ~]$ [ $myVar = "a b" ]; echo $? bash: [: too many arguments 2 # ПРАВИЛЬНО [andreyex@linux ~]$ [ "$myVar" = "a b" ]; echo $? 0
Еще одна ошибка заключается в неправильном использовании пробелов в команде [. Как мы обсуждали ранее в этом посте, конструкция [ — это встроенная команда оболочки, похожая на команду test. Таким образом, после имени команды должен быть пробел перед первым аргументом, и каждый аргумент, включая операторы сравнения, должен содержать пробелы.
[andreyex@linux ~]$ var="Example String" # НЕПРАВИЛЬНО: отсутствие пробела вокруг команды `[` приведет к ошибке bash "команда не найдена" [andreyex@linux ~]$ if [string="$var"]; then echo ${var}; fi bash: [string=]: command not found # НЕПРАВИЛЬНО: Пропущенный пробел вокруг оператора приведет к ошибочному возвращению выражения как true [andreyex@linux ~]$ if [ string="$var" ]; then echo ${var}; fi Example String # ПРАВИЛЬНОЕ использование пробелов с помощью команды [ [andreyex@linux ~]$ if [ string = "$var" ]; then echo ${var}; fi
[andreyex@linux ~]$ a=b; c=d; # НЕПРАВИЛЬНОЕ использование && [andreyex@linux ~]$ if [ $a = b && $c = d ]; then echo "Success"; fi bash: [: missing `]' # ПРАВИЛЬНОЕ использование && [andreyex@linux ~]$ if [ $a = b ] && [ $c = d ]; then echo "Success"; fi Success
Причина ошибки Bash binary operator expected обычно заключается в том, что переменная расширяется до нескольких слов и неправильно заключена в кавычки при использовании с командой test or [. Если вам не требуется, чтобы ваш скрипт был на 100% совместим с POSIX, лучшей альтернативой является использование встроенной команды [[ в bash, на которую не повлияет разделение слов или расширение глобуса.
[andreyex@linux ~]$ string="word1 word2" # НЕВЕРНО: Пропущенные кавычки [andreyex@linux ~]$ if [ -n $string ]; then echo "\$string length >0"; fi bash: [: word1: binary operator expected # ПРАВИЛЬНО [andreyex@linux ~]$ if [ -n "$string" ]; then echo "\$string length >0"; fi $string length >0 # ПРАВИЛЬНО и лучше в bash [andreyex@linux ~]$ if [[ -n $string ]]; then echo "\$string length >0"; fi $string length >0
Попытка эмулировать троичный оператор с помощью двоичных операторов || (или) и && (и) может привести к ошибкам и неожиданным результатам. По возможности предпочитайте обычные конструкции инструкции if. Основная проблема заключается в том, что команда && также будет генерировать статус завершения и может привести к тому, что команда после || будет выполнена.
# Неверно/Не рекомендуется [[ ! -f myFile ]] && myCommandOnSuccess || myCommandOnFailure # Правильная/наилучшая практика if [[ -f myFile ]]; then myCommandOnSuccess else myCommandOnFailure fi # НЕПРАВИЛЬНО: все команды выполнены [andreyex@linux ~]$ [[ ! -f myFile ]] && { echo "File not found"; false; } || { echo "File exist"; true; } File not found File exist # НЕПРАВИЛЬНО: все арифметические разложения выполняются и возвращают неверное значение z [andreyex@linux ~]$ z=0; [[ -v z ]] && ((z++)) || ((z--)); echo $z 0 # ИСПРАВИТЬ, если в инструкции bash используется [andreyex@linux ~]$ z=0; if [[ -v z ]]; then ((z++)); else ((z--)); fi; echo $z 1 # КОРРЕКТНО только для арифметических расширений и не может использовать -v [andreyex@linux ~]$ z=0; (( z==0 ? z++ : z-- )); echo $z 0
Ниже приведены некоторые распространенные примеры и варианты использования инструкции if и условных выражений в Bash.
Для проверки того, существует ли переменная или имеет значение null, в Bash можно использовать три основных выражения условного выражения: -v, -n и -z.
👉 В оболочке Bash нет определения переменной null. Мы будем говорить либо о том, установлена переменная, либо о том, что она не установлена. Обратите внимание, что переменная может быть задана с пустой строкой (строка нулевой длины с использованием двойных кавычек «») или без значения, которое может быть указано как нулевое значение. Эту терминологию не следует путать с командой Null в Bash, которая имеет совершенно другое назначение.
# Переменная не существует [andreyex@linux ~]$ [[ -v myVar ]] ; echo "Condition returned $?" Condition returned 1 # Переменная установлена и существует [andreyex@linux ~]$ myVar="test" [andreyex@linux ~]$ [[ -v myVar ]] ; echo "Condition returned $?" Condition returned 0 # Переменная имеет значение строки нулевой длины (null/empty) и существует [andreyex@linux ~]$ myVar= [andreyex@linux ~]$ [[ -v myVar ]] ; echo "Condition returned $?" Condition returned 0 # Переменная не установлена и не существует [andreyex@linux ~]$ unset myVar [andreyex@linux ~]$ [[ -v myVar ]] ; echo "Condition returned $?" Condition returned 1
-n и -z также будут проверять длину строки. Параметр -n проверяет ненулевую длину, а параметр -z проверяет строку нулевой длины. Эти первичные параметры могут быть полезны, если вы намерены проверить, является ли переменная пустой или нет. Однако будьте осторожны, если ваш сценарий оболочки выполняется с опцией set -u, а ваша переменная не существует, тогда ваш сценарий завершится с ошибкой типа bash: myVar: unbound variable.
Чтобы обойти это, вы можете протестировать с расширением параметра, используя ${parameter:+word}, чтобы убедиться, что переменная установлена. Вы также можете комбинировать использование -v и -z, таких как [[ -v varName && -z $varName ]]. Я нахожу последнюю структуру более понятной, поскольку она переводится в “если моя переменная существует, а длина моей переменной равна нулю (-z) / ненулевому значению (-n), то …”, хотя это несколько иное поведение, чем просто использование решения для расширения параметров.
[andreyex@linux ~]$ unset myVar # Проверка на переменную длины, превышающую ноль, при отключенном myVar [andreyex@linux ~]$ [[ -z $myVar ]] ; echo "Condition returned $?" Condition returned 0 # Проверка на переменную длину, равную нулю, при отключенном myVar [andreyex@linux ~]$ [[ -n $myVar ]] ; echo "Condition returned $?" Condition returned 1 # Тест на переменную длину с набором myVar [andreyex@linux ~]$ myVar="test" [andreyex@linux ~]$ [[ -z $myVar ]] ; echo "Condition returned $?" Condition returned 1 [andreyex@linux ~]$ [[ -n $myVar ]] ; echo "Condition returned $?" Condition returned 0 # НЕКОРРЕКТНЫЙ тест для переменной длины с параметром set -u и расширением параметров [andreyex@linux ~]$ unset myVar ; set -u [andreyex@linux ~]$ [[ -z $myVar ]] ; echo "Condition returned $?" bash: myVar: unbound variable # КОРРЕКТНЫЕ тесты с не заданной переменной [andreyex@linux ~]$ unset myVar ; set -u [andreyex@linux ~]$ [[ -z ${myVar:+x} ]] ; echo "Condition returned $?" Condition returned 0 [andreyex@linux ~]$ [[ -n ${myVar:+x} ]] ; echo "Condition returned $?" Condition returned 1 # ИСПРАВЬТЕ, если вы считаете, что неустановленная переменная не совпадает с переменной нулевой длины # Условие возвращает "False" в обоих случаях [andreyex@linux ~]$ [[ -v myVar && -z $myVar ]] ; echo "Condition returned $?" Condition returned 1 [andreyex@linux ~]$ [[ -v myVar && -n $myVar ]] ; echo "Condition returned $?" Condition returned 1 # КОРРЕКТНЫЕ тесты с пустой переменной [andreyex@linux ~]$ myVar="" ; set -u [andreyex@linux ~]$ [[ -v myVar && -z $myVar ]] ; echo "Condition returned $?" Condition returned 0 [andreyex@linux ~]$ [[ -z ${myVar:+x} ]] ; echo "Condition returned $?" Condition returned 1 [andreyex@linux ~]$ [[ -v myVar && -n $myVar ]] ; echo "Condition returned $?" Condition returned 1 [andreyex@linux ~]$ [[ -n ${myVar:+x} ]] ; echo "Condition returned $?" Condition returned 1 # КОРРЕКТНЫЕ тесты с непустой переменной [andreyex@linux ~]$ myVar="test" [andreyex@linux ~]$ [[ -v myVar && -z $myVar ]] ; echo "Condition returned $?" 1 [andreyex@linux ~]$ [[ -z ${myVar:+x} ]] ; echo "Condition returned $?" Condition returned 1 [andreyex@linux ~]$ [[ -v myVar && -n $myVar ]] ; echo "Condition returned $?" Condition returned 0 [andreyex@linux ~]$ [[ -n ${myVar:+x} ]] ; echo "Condition returned $?" Condition returned 0
Вы можете использовать выражение в одной скобке с этими основными параметрами, но вам нужно обязательно заключать переменную в кавычки при проверке длины строки с помощью -z и -n, чтобы предотвратить разделение слов или расширение глобуса. Двойные скобки в кавычках не нужны, поскольку это поведение по умолчанию.
-f Primary можно использовать для проверки, существует ли обычный файл или нет.
[andreyex@linux ~]$ touch myfile [andreyex@linux ~]$ if [[ -f myfile ]]; then echo "myfile exists. If Statement Condition equal $?."; fi myfile exists. If Statement Condition equal 0. [andreyex@linux ~]$ if [ -f myfile ]; then echo "myfile exists. If Statement Condition equal $?."; fi myfile exists. If Statement Condition equal 0. [andreyex@linux ~]$ if test -f myfile; then echo "myfile exists. If Statement Condition equal $?."; fi myfile exists. If Statement Condition equal 0.
Помните, что условные выражения будут следовать символическим ссылкам при тестировании файлов и будут выполнять тест для целевого объекта ссылки. Следовательно, тест вернет 1 (false)), когда символические ссылки указывают на несуществующий файл или если у вас нет надлежащего разрешения на доступ к целевому файлу. Чтобы проверить, существует ли обычный файл или соответствующие символические ссылки, можно было бы протестировать с объединением -f и -L первичных файлов.
[andreyex@linux ~]$ touch myfile ; ln -s broken_target broken_link # протестируйте с помощью -f обычный файл и неработающую символическую ссылку [andreyex@linux ~]$ [[ -f myfile ]]; echo $? 0 [andreyex@linux ~]$ [[ -f broken_link ]]; echo $? 1 # протестируйте с помощью -L обычный файл и неработающую символическую ссылку [andreyex@linux ~]$ [[ -L myfile ]]; echo $? 1 [andreyex@linux ~]$ [[ -L broken_link ]]; echo $? 0 # Комбинированный тест на наличие файла или символической ссылки [andreyex@linux ~]$ [[ -f broken_link || -L broken_link ]]; echo $? 0
-d Primary можно использовать для проверки того, существует каталог или нет.
[andreyex@linux ~]$ mkdir myDir [andreyex@linux ~]$ if [[ -d myDir ]]; then echo "myDir exists. If Statement Condition equal $?."; fi myDir exists. If Statement Condition equal 0. [andreyex@linux ~]$ if [ -d myDir ]; then echo "myDir exists. If Statement Condition equal $?."; fi myDir exists. If Statement Condition equal 0. [andreyex@linux ~]$ if test -d myDir; then echo "myDir exists. If Statement Condition equal $?."; fi myDir exists. If Statement Condition equal 0.
Инструкция if в bash принимает команду и проверяет код завершения этой команды, используя синтаксис if <command>; then <code>; fi.
Если вы не собираетесь использовать значение кода выхода вашей команды, не используйте код состояния выхода с помощью $?, это не нужно и может привести к ошибкам при использовании с set -e.
# КОРРЕКТНО [andreyex@linux ~]$ if grep -q RegPattern "$myfile"; then echo "Found RegPattern in $myfile" fi # НЕ РЕКОМЕНДУЕТСЯ [andreyex@linux ~]$ grep -q RegPattern "$myfile" [andreyex@linux ~]$ if [ $? -eq 0 ]; then echo "Found RegPattern in $myfile"; fi
При использовании [[оператор== можно использовать для проверки равенства строк в Bash. Помните, что [[…]] составная команда выполнит сопоставление с шаблоном, где правая сторона может быть шаблоном глобуса. Следовательно, чтобы предотвратить глобализацию и проверить равенство строк, обязательно заключите правую часть условного выражения в кавычки.
👉 Подробнее о глобировании и шаблонах глобуса читайте в моем посте о том, как использовать подстановочные знаки Bash для глобирования.
[andreyex@linux ~]$ myString1=abc ; myString2=ab* # Без кавычек Bash выполнит шаблон glob и не сможет должным образом проверить равенство [andreyex@linux ~]$ [[ $myString1 == $myString2 ]]; echo $? 0 [andreyex@linux ~]$ [[ $myString1 == "$myString2" ]]; echo $? 1 # Исправьте проверку на равенство строк с помощью оператора if в bash [andreyex@linux ~]$ if [[ $myString1 == "$myString2" ]]; then echo "\$myString1 equals to \$myString2 with the string: $myString1"; else echo "\$myString1 and \$myString2 are different with \$myString1=$myString1 and \$myString2=$myString2"; fi
Если ваш сценарий оболочки требует соответствия POSIX, вам нужно будет протестировать с помощью команд test or [ и использовать оператор =. Кавычки становятся неактуальными в тех случаях, когда test и [ не выполняют глобализацию.
Если вы хотите протестировать строки на соответствие регулярному выражению, вам нужно будет использовать =~ оператор и сначала определить регулярное выражение, поскольку использование кавычек приведет к тому, что ваше регулярное выражение будет обрабатываться как строка.
[andreyex@linux ~]$ myString="ab c" ; myRegex='[[:alpha:]]+.*' # Проверьте строку на соответствие шаблону регулярных выражений [andreyex@linux ~]$ [[ $myString =~ $myRegex ]]; echo $? 0 # Это завершилось бы неудачей, поскольку оно проверялось на соответствие строковому значению регулярного выражения [andreyex@linux ~]$ [[ $myString =~ "$myRegex" ]]; echo $? 1
Для поиска точного соответствия вашему regex шаблону необходимо добавить дополнительные пробелы перед и после значения like (^|[[:space:]])»VALUE»($|[[:space:]]).
[andreyex@linux ~]$ declare -A myAssociativeArray; myAssociativeArray=([a]=123 [b]=456) [andreyex@linux ~]$ [[ ${myAssociativeArray[*]} =~ (^|[[:space:]])"12"($|[[:space:]]) ]] ; echo $? 1 [andreyex@linux ~]$ [[ ${myAssociativeArray[*]} =~ (^|[[:space:]])"123"($|[[:space:]]) ]] ; echo $? 0
Смотрите подробные примеры в посте: массивы в Bash.
В Bash нет тернарного оператора, хотя при использовании арифметического расширения ((…)) конструкция в двойных круглых скобках поддерживает вопросительный знак ? как элемент тернарного (или тройного) оператора в стиле C, например (( condition ? result-if-true : result-if-false )). На мой взгляд, он имеет ограниченный вариант использования, поскольку в большинстве случаев было бы более уместно просто проверить условие, используя стандартный возвращаемый код выхода 0 or 1.
[andreyex@linux ~]$ myVar=12 ; echo $((myVar>10?true:false)) ; echo $((myVar>10?17:3)) 0 17
Использование операторов && и || для эмуляции троичного оператора в сценарии оболочки не рекомендуется, поскольку это чревато ошибками, см. Раздел ниже о почему вы не должны использовать операторы || и && вместо инструкции if в bash.
Чтобы отменить любое условие, используйте оператор !, например: if ! <test-command>; then <command-on-failure>; fi. Обратите внимание, что пробел между ! и следующей командой важен, в противном случае она выполнила бы расширение bash history и, скорее всего, вернула бы ошибку bash event not found.
Для сравнения строк в условном выражении можно использовать оператор not equal !=, например, string1 != string2.
Ниже приведен пример отрицательного условия для команды grep.
if ! grep -q lookupWord "$myFile"; then echo 'Failed to grep'; fi
Условный оператор регулярного выражения =~ принимает строковое значение в левой части и расширенное регулярное выражение Bash в правой части оператора. Синтаксис: *string1* =~ *regex*. Оператор возвращает код выхода 0 (True), если строки соответствуют регулярному выражению regex.
Переменная $BASH_REMATCH — это массив Bash=~, доступный только для чтения, содержащий значения, сопоставленные расширенному регулярному выражению в правой части [[ двоичного оператора в условном выражении с двойными скобками, заключенном в две скобки. Захваченные группы хранятся в переменной массива BASH_REMATCH. Строке, соответствующей всему регулярному выражению, присваивается первый индекс (0) массива. Следующие элементы в массиве с индексом n соответствуют строке, соответствующей n-му подвыражению, заключенному в скобки.
[andreyex@linux ~]$ shopt -s extglob [andreyex@linux ~]$ var="This is An Example of Bash Extended Regular Expression" [andreyex@linux ~]$ [[ "$var" =~ Regular ]] && echo "Word 'Regular' found. BASH_REMATCH=${BASH_REMATCH[@]}" Word 'Regular' found. BASH_REMATCH=Regular [andreyex@linux ~]$ [[ "$var" =~ (a) ]] && echo "Letter 'a' found. BASH_REMATCH=${BASH_REMATCH[@]}"