Spec-Zone.ru › Bash

Условные конструкции

​
​ ​ ​ ​if

Синтаксис команды if:

if test-commands; then
  consequent-commands;
[elif more-test-commands; then
  more-consequents;]
[else alternate-consequents;]
fi

Список test-commands выполняется, и если его код возврата равен нулю, выполняется список consequent-commands. Если test-commands возвращает ненулевой код, по очереди выполняется каждый список elif, и если его код завершения равен нулю, выполняется соответствующий список more-consequents, после чего команда завершается. Если указано ‘else alternate-consequents’ и последняя команда в последнем предложении if или elif имеет ненулевой код завершения, выполняется alternate-consequents. Код возврата совпадает с кодом завершения последней выполненной команды или равен нулю, если ни одно условие не оказалось истинным.

​ ​case

Синтаксис команды case:

case word in
    [ [(] pattern [| pattern]...) command-list ;;]...
esac

case выборочно выполняет command-list, соответствующий первому шаблону pattern, которому соответствует word, проверяя шаблоны по порядку, от первого до последнего. Сопоставление выполняется согласно правилам, описанным ниже в разделе Сопоставление с шаблоном. Если включён параметр оболочки nocasematch (см. описание shopt в разделе Встроенная команда shopt), сопоставление выполняется без учёта регистра букв. Символ ‘|’ используется для разделения нескольких шаблонов в списке шаблонов, а оператор ‘)’ завершает список шаблонов. Список шаблонов и связанный с ним command-list называются clause.

Каждое предложение должно завершаться символами ‘;;’, ‘;&’ или ‘;;&’. Перед тем как оболочка попытается сопоставить шаблон, к word применяются раскрытие тильды, раскрытие параметров, подстановка команд, подстановка процессов, арифметическое раскрытие и удаление кавычек (см. Раскрытие параметров оболочки). К каждому pattern применяются раскрытие тильды, раскрытие параметров, подстановка команд, арифметическое раскрытие, подстановка процессов и удаление кавычек.

Число предложений case может быть произвольным; каждое завершается символами ‘;;’, ‘;&’ или ‘;;&’. Первый совпавший шаблон определяет список команд, который будет выполнен. Часто в качестве последнего шаблона используют ‘*’, задавая тем самым вариант по умолчанию, поскольку этот шаблон совпадает всегда.

Ниже приведён пример использования case в скрипте, который можно использовать для описания одной интересной особенности животного:

echo -n "Enter the name of an animal: "
read ANIMAL
echo -n "The $ANIMAL has "
case $ANIMAL in
  horse | dog | cat) echo -n "four";;
  man | kangaroo ) echo -n "two";;
  *) echo -n "an unknown number of";;
esac
echo " legs."

Если используется оператор ‘;;’, выполнение команды case завершается после первого совпадения с шаблоном. Использование ‘;&’ вместо ‘;;’ приводит к тому, что выполнение продолжается со списком command-list, связанным со следующим предложением, если оно есть. Использование ‘;;&’ вместо ‘;;’ приводит к тому, что оболочка проверяет шаблоны в следующем предложении, если оно есть, и выполняет связанный список command-list, если найдено совпадение; выполнение оператора case продолжается так, как если бы список шаблонов не совпал.

Код возврата равен нулю, если ни один pattern не совпал. В противном случае код возврата совпадает с кодом завершения последнего выполненного списка command-list.

select

Конструкция select позволяет легко создавать меню. Её синтаксис почти совпадает с синтаксисом команды for:

select name [in words ...]; do commands; done

Сначала раскрывается список слов после in, формируя перечень элементов, после чего набор раскрытых слов выводится в стандартный поток ошибок, каждое слово предваряется номером. Если ‘in words’ опущено, выводятся позиционные параметры, как если бы было указано ‘in "$@"’. Затем select выводит приглашение PS3 и считывает строку из стандартного ввода. Если строка состоит из числа, соответствующего одному из выведенных слов, select присваивает переменной name это слово. Если строка пуста, select снова выводит слова и приглашение. Если считано EOF, выполнение select завершается с кодом возврата 1. При любом другом введённом значении переменной name присваивается значение null. Считанная строка сохраняется в переменной REPLY.

commands выполняются после каждого выбора, пока не будет выполнена команда break; после этого выполнение команды select завершается.

Ниже приведён пример, позволяющий пользователю выбрать имя файла из текущего каталога и выводящий имя и индекс выбранного файла.

select fname in *;
do
	echo you picked $fname \($REPLY\)
	break;
done
((…))
(( expression ))

Арифметическое expression вычисляется согласно правилам, описанным ниже (см. Арифметика оболочки). К expression применяются те же преобразования, что и в случае, если бы оно находилось в двойных кавычках, однако неэкранированные символы двойной кавычки в expression не обрабатываются особым образом и удаляются. Поскольку в результате могут получиться пустые строки, эта команда рассматривает их как выражения, значение которых равно 0. Если значение выражения отлично от нуля, код возврата равен 0; в противном случае код возврата равен 1.

​[[…]]
[[ expression ]]

Вычисляет условное выражение expression и возвращает нулевой статус (истина) или ненулевой (ложь). Выражения состоят из примитивов, описанных ниже в разделе Условные выражения Bash. Слова между [[ и ]] не подвергаются разбиению на слова и подстановке имён файлов. Для этих слов оболочка выполняет раскрытие тильды, раскрытие параметров и переменных, арифметическое раскрытие, подстановку команд, подстановку процессов и удаление кавычек. Условные операторы, такие как ‘-f’, должны быть без кавычек, чтобы распознаваться как примитивы.

При использовании с [[ операторы ‘<’ и ‘>’ выполняют лексикографическую сортировку с учётом текущей локали.

При использовании операторов ‘==’ и ‘!=’ строка справа от оператора рассматривается как шаблон и сопоставляется согласно правилам, описанным ниже в разделе Сопоставление с шаблоном, как если бы был включён параметр оболочки extglob. Оператор ‘=’ идентичен оператору ‘==’. Если включён параметр оболочки nocasematch (см. описание shopt в разделе Встроенная команда shopt), сопоставление выполняется без учёта регистра букв. Возвращаемое значение равно 0, если строка соответствует (‘==’) шаблону или не соответствует ему (‘!=’), и 1 в противном случае.

Если заключить любую часть шаблона в кавычки с помощью любого из способов цитирования оболочки, эта часть будет сопоставляться буквально. Это означает, что каждый символ в заключённой в кавычки части соответствует самому себе, а не имеет какого-либо специального значения для сопоставления с шаблоном.

Доступен дополнительный бинарный оператор ‘=~’ с тем же приоритетом, что и у операторов ‘==’ и ‘!=’. При использовании ‘=~’ строка справа от оператора рассматривается как шаблон расширенного регулярного выражения POSIX и сопоставляется соответствующим образом (с использованием интерфейсов POSIX regcomp и regexec, обычно описываемых в regex(3)). Возвращаемое значение равно 0, если строка соответствует шаблону, и 1, если не соответствует. Если регулярное выражение синтаксически некорректно, условное выражение возвращает 2. Если включён параметр оболочки nocasematch (см. описание shopt в разделе Встроенная команда shopt), сопоставление выполняется без учёта регистра букв.

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

Сопоставление успешно, если шаблон соответствует любой части строки. Чтобы заставить шаблон соответствовать всей строке, заякорите его с помощью операторов регулярных выражений ‘^’ и ‘$’.

Например, следующий шаблон соответствует строке (сохранённой в переменной оболочки line), если где-либо в её значении имеется последовательность символов, состоящая из любого числа (включая ноль) символов класса символов space, за которыми непосредственно следует ноль или одно вхождение ‘a’, а затем ‘b’:

[[ $line =~ [[:space:]]*(a)?b ]]

Это означает, что будут соответствовать такие значения line, как ‘aab’, ‘ aaaaaab’, ‘xaby’ и ‘ ab’, а также любая строка, содержащая ‘b’ где-либо в своём значении.

Чтобы сопоставить символ, имеющий специальное значение в грамматике регулярных выражений (‘^$|[]()\.*+?’), его необходимо заключить в кавычки, чтобы убрать это специальное значение. Это означает, что в шаблоне ‘xxx.txt’ символ ‘.’ соответствует любому символу в строке (как обычно в регулярных выражениях), а в шаблоне ‘"xxx.txt"’ он может соответствовать только буквальному символу ‘.’.

Аналогично, если нужно включить в шаблон символ, имеющий специальное значение в грамматике регулярных выражений, необходимо убедиться, что он не заключён в кавычки. Например, если шаблон требуется заякорить в начале или конце строки, символы ‘^’ и ‘$’ нельзя заключать в кавычки ни одним из способов цитирования оболочки.

Чтобы сопоставить ‘initial string’ в начале строки, подойдёт следующий вариант:

[[ $line =~ ^"initial string" ]]

а этот вариант не подойдёт:

[[ $line =~ "^initial string" ]]

поскольку во втором примере символ ‘^’ заключён в кавычки и не имеет своего обычного специального значения.

Иногда бывает трудно задать регулярное выражение правильно, не используя кавычки, или отслеживать цитирование, используемое регулярными выражениями, одновременно учитывая цитирование оболочки и удаление кавычек оболочкой. Часто удобно сохранять регулярное выражение в переменной оболочки — это помогает избежать проблем с цитированием символов, имеющих специальное значение для оболочки. Например, следующий вариант эквивалентен шаблону, использованному выше:

pattern='[[:space:]]*(a)?b'
[[ $line =~ $pattern ]]

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

Следующие два набора команд не эквивалентны:

pattern='\.'

[[ . =~ $pattern ]]
[[ . =~ \. ]]

[[ . =~ "$pattern" ]]
[[ . =~ '\.' ]]

Первые два сопоставления будут успешными, а вторые два — нет, поскольку во вторых двух примерах обратная косая черта будет частью сопоставляемого шаблона. В первых двух примерах парсеру регулярных выражений передаётся шаблон ‘\.’. Обратная косая черта снимает специальное значение с символа ‘.’, поэтому происходит сопоставление с буквальным символом ‘.’. Во вторых двух примерах парсеру регулярных выражений передаётся шаблон, в котором обратная косая черта заключена в кавычки (например, ‘\\\.’); он не будет соответствовать строке, поскольку та не содержит обратной косой черты. Если бы строка в первых примерах содержала что-либо, кроме ‘.’, например ‘a’, шаблон не совпал бы, поскольку заключённый в кавычки символ ‘.’ в шаблоне теряет своё специальное значение, позволяющее ему соответствовать любому одиночному символу.

Выражения в квадратных скобках в регулярных выражениях также могут быть источником ошибок, поскольку символы, обычно имеющие специальное значение в регулярных выражениях, теряют его внутри квадратных скобок. Однако выражения в квадратных скобках можно использовать для сопоставления со специальными символами шаблона без заключения их в кавычки, поэтому иногда это бывает полезно.

Хотя такая запись может показаться необычной, следующий шаблон будет соответствовать символу ‘.’ в строке:

[[ . =~ [.] ]]

Оболочка выполняет раскрытие слов до передачи шаблона функциям регулярных выражений, поэтому можно считать, что цитирование оболочки имеет приоритет. Как отмечалось выше, после раскрытия оболочки парсер регулярных выражений интерпретирует все оставшиеся в шаблоне незаключённые в кавычки обратные косые черты согласно собственным правилам. Задача состоит в том, чтобы по возможности не заставлять программистов оболочки цитировать символы дважды, поэтому цитирования оболочки должно быть достаточно для цитирования специальных символов шаблона, когда это необходимо.

Массив BASH_REMATCH содержит сведения о том, какие части строки соответствовали шаблону. Элемент BASH_REMATCH с индексом 0 содержит часть строки, соответствующую всему регулярному выражению. Подстроки, соответствующие подвыражениям в круглых скобках внутри регулярного выражения, сохраняются в остальных индексах BASH_REMATCH. Элемент BASH_REMATCH с индексом n содержит часть строки, соответствующую n-му подвыражению в круглых скобках.

Bash задаёт BASH_REMATCH в глобальной области видимости; объявление этой переменной как локальной приведёт к непредвиденным результатам.

Выражения можно объединять с помощью следующих операторов, перечисленных в порядке убывания приоритета:

( expression )

Возвращает значение expression. Это можно использовать для изменения обычного приоритета операторов.

! expression

Истина, если expression ложно.

expression1 && expression2

Истина, если оба выражения — expression1 и expression2 — истинны.

expression1 || expression2

Истина, если истинно хотя бы одно из выражений — expression1 или expression2.

Операторы && и || не вычисляют expression2, если значения expression1 достаточно, чтобы определить возвращаемое значение всего условного выражения.

Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
Licensed under the GNU Free Documentation License.
https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API