BASH. Часть 6. Раскрытие выражений

Когда оболочка получает какую-то командную строку на выполнение, она до начала выполнения команды осуществляет «грамматический разбор» полученной командной строки. Одним из этапов такого «разбора» является раскрытие или подстановка выражений (expansion). В оболочке bash имеется семь типов подстановки выражений:

  • раскрытие скобок (brace expansion);
  • замена знака тильды (tilde expansion);
  • подстановка параметров и переменных;
  • подстановка команд;
  • арифметические подстановки (выполняемые слева направо);
  • разделение слов (word splitting);
  • раскрытие шаблонов имен файлов и каталогов (pathname expansion).

Все эти операции выполняются именно в том порядке, как они здесь перечислены. Рассмотрим их последовательно.

Раскрытие скобок

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

[user]$ mkdir /usr/local/src/bash/ {old, new, dist, bugs}
[root]# chown root /usr/{ucb/{ex, edit} , lib/{ex?.?*, how_ex}}

В первом случае в каталоге /usr/local/src/bash/ будут созданы подкаталоги old, new, dist и bugs. Во втором случае владелец будет изменен у файлов:

/usr/ucb/ex
/usr/ucb/ex
/usr/lib/ex?.?*
/usr/lib/how_ex
/usr/ucb/edit
/usr/ucb/edit
/usr/lib/ex?.?*
/usr/lib/how_ex

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

Еще один пример: строка a{d,c,b}e при раскрытии скобок превращается в три слова ade асе abe. Раскрытие скобок выполняется до выполнения других видов подстановок в командной строке, причем все специальные символы, встречающиеся в командной строке, в том числе внутри скобок, сохраняются неизменными (они будут интерпретированы на следующих этапах анализа строки).

Замена тильды

Если слово начинается с символа тильды (~), все символы до первого слэша (или все символы, если слэша нет) трактуются как имя пользователя (login name). Если это имя есть пустая строка (то есть вслед за тильдой идет сразу слэш), то тильда заменяется на значение переменной НОМЕ. Если значение переменной НОМЕ не задано, тильда заменяется на полный путь к домашнему каталогу пользователя, запустившего оболочку.

Если вслед за знаком тильды (до слэша) стоит слово, совпадающее с именем одного из легальных пользователей, тильда и имя пользователя заменяются полным именем домашнего каталога этого пользователя. Если слово, следующее за тильдой, не является именем пользователя (и не пусто), то оно остается неизменным. Если вслед за знаком тильды стоит +, эти два знака заменяются на полное имя текущего каталога (то есть значение переменной PWD). Если за знаком тильды следует -, подставляется значение переменой OLDPWD.

Подстановка параметров и переменных

Символ $ используется для обозначения операций подстановки параметров, подстановки команд и подстановок арифметических выражений. Выражение или имя, следующее за $, может быть заключено в скобки; что необязательно, но удобно, т. к. позволяет отделить заменяемое выражение от следующих за ним слов или символов. Таким образом, чтобы в командной строке вызвать значение параметра (в частности, любой переменной), нужно вставить выражение вида $ {parameter}. Скобки необходимы только в том случае, если имя параметра состоит из нескольких цифр, или когда за именем следует символ, который не должен интерпретироваться как часть имени. Все значения переменных подвергаются подстановке знака тильды, раскрытию параметров и переменных, подстановке команд, подстановкам арифметических выражений, а также удалению специальных символов цитирования (см. ниже). Разделение слов не производится, за исключением случая «$@» (объяснение ниже ). Раскрытие шаблонов имен файлов и каталогов не производится.

Подстановка команд

Подстановка команд является очень мощным инструментом bash. Она заключается в замене имени команды на результат ее выполнения. Существует две формы подстановки команд:

$(command) и ‘command’

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

Арифметичекие подстановки

Арифметические подстановки позволяют вычислить значение арифметического выражения и подставить вместо него результат. Существует две формы задания арифметических подстановок:

$[expression]
$((expression))

где expression трактуется так, как если бы оно было заключено в двойные кавычки, но встречающиеся в expression двойные кавычки трактуются как простой литерал. Внутри expression выполняются подстановки параметров и команд.
Синтаксис выражения expression подобен синтаксису арифметических выражений в языке С, подробнее об этом можно прочитать в разделе ARITHMETIC EVALUATION man-страницы по команде bash. Например, команда

[user]$ echo $ ((2 + 3 * 5))

в качестве результата выдает «17». Если выражение некорректно, bash выдает сообщение об ошибке.

Разделение слов

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

Раскрытие шаблонов имен файлов и каталогов

Подстановки имен путей и файлов (pathname expansion) используются для того, чтобы с помощью краткого образца или шаблона указать несколько имен файлов (или каталогов), соответствующих данному шаблону. После разделения слов, если не была задана опция -f, bash производит поиск в каждом слове командной строки символов *, ? и [. Если будет найдено слово с одним или несколькими вхождениями таких символов, то это слово рассматривается как шаблон, который должен быть заменен словами из лексикографически упорядоченного списка имен путей, соответствующих данному шаблону. Если имен, соответствующих шаблону, не найдено, и переменная nullglob не задана, слово не изменяется. Если эта переменная установлена, а путей, соответствующих шаблону, не найдено, слово удаляется из командной строки. Специальные символы шаблонов имеют следующее значение:

Символы шаблонов

* — Соответствует произвольной строке символов, включая пустую строку. Например, my*.txt будет заменено на myday.txt, myweek.txt и mymonth.txt (если такие файлы существуют), a *.jpg соответствует всем файлам с расширением jpg в указанном каталоге

? — Соответствует любому одиночному символу. Например, вместо шаблона file?.txt будут подставлены имена file1.txt и filex.txt, но не file10.txt

[…] — Соответствует любому символу из числа символов, указанных в скобках. Пары символов, разделенные знаком минуса, обозначают интервал; любой символ стоящий лексически между этими двумя символами, включая и символы, задающие интервал, соответствует шаблону. Если первым символом внутри скобок является (!) или (^), то считается, что шаблону (в данной позиции) соответствуют все символы, не указанные в скобках.

Шаблоны имен файлов очень часто применяются в командных строках, содержащих команду ls. Представьте себе, что вы хотите просмотреть информацию о содержимом каталога, в котором находится огромное количество разных файлов различных форматов, например, файлов с изображениями форматов GIF, JPEG, AVI и т. д. Чтобы получить только список файлов формата JPEG, вы можете использовать команду

[user]$ ls *.jpg

Если в каталоге имеется множество файлов, имена которых представлены четырехзначными номерами, то следующей командой можно вывести только список файлов с номерами от 0200 до 0499:

[user]$ ls -l 0[2-4]??.*

Удаление специальных символов

После того как все подстановки в командной строке сделаны, из нее еще удаляются все вхождения символов , ‘ и «, которые служили для отмены специального значения других символов.

Другие части.

BASH. Часть 1. Введение.
BASH. Часть 2. Специальные символы.
BASH. Часть 3. Выполнение команд.
BASH. Часть 4. Стандартный ввод/вывод.
BASH. Часть 5. Параметры и переменные. Окружение оболочки.
BASH. Часть 6. Раскрытие выражений.

По книге В.Костромина «Linux для пользователя».