Выбрать главу

Группы команд и подоболочки

bash поддерживает возможность группировки команд. Воспользоваться ею можно двумя способами: либо путем группировки команд, либо путем применения под­оболочки. Ниже приводятся примеры синтаксиса обоих подходов.

Группа команд:

{ команда1; команда2; [команда3; ...] }

Подоболочка:

(команда1; команда2; [команда3;...])

Группа команд заключается в фигурные скобки, а подоболочка оформляется круглыми скобками. Вот и вся разница. Однако обратите внимание, что из-за особенностей реализации группировки команд в bash фигурные скобки должны отделяться от команд пробелами и последняя команда должна завершаться точкой с запятой или символом перевода строки.

Перенаправление

Итак, где могут пригодиться группы команд и подоболочки? Даже при том, что между ними имеются важные различия (которые будут раскрыты далее), и те и другие используются в основном для перенаправления. Рассмотрим фрагмент сценария, выполняющий перенаправление вывода множества команд:

ls -l > output.txt

echo "Listing of foo.txt" >> output.txt

cat foo.txt >> output.txt

Выглядит достаточно просто: вывод трех команд перенаправляется в файл с именем output.txt. Воспользовавшись приемом группировки, то же самое можно выразить более кратко:

{ ls -l; echo "Listing of foo.txt"; cat foo.txt; } > output.txt

Подоболочка используется аналогично:

(ls -l; echo "Listing of foo.txt"; cat foo.txt) > output.txt

Этот прием помог нам сэкономить силы и время на вводе текста сценария, но истинная мощь групп команд и подоболочек проявляется в конвейерах. Создавая конвейеры из команд, мы часто сталкиваемся с необходимостью объединения результатов нескольких команд в общий поток. Группы команд и подоболочки упрощают эту задачу:

{ ls -l; echo "Listing of foo.txt"; cat foo.txt; } | lpr

Здесь мы объединили вывод трех команд и передали его по конвейеру на вход команды lpr, чтобы напечатать отчет.

Подстановка процессов

Несмотря на внешнее сходство и возможность объединения потоков для последующего перенаправления, между группами команд и подоболочками существуют важные отличия. Все команды, входящие в группу, выполняются в текущей оболочке, подоболочка (как можно догадаться из названия) выполняет свои команды в дочерней копии текущей командной оболочки. Это означает, что в момент запуска подоболочки создается копия текущей оболочки и передается новому экземпляру оболочки. Когда подоболочка завершается, ее копия окружения уничтожается, соответственно теряются любые изменения в окружении подоболочки (включая значения переменных).

Поэтому если нет прямой необходимости в использовании подоболочки, предпочтительнее использовать группы команд. Группы команд выполняются быстрее и требуют меньше памяти.

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

echo "foo" | read

echo $REPLY

после выполнения которого переменная REPLY всегда оставалась пустой, потому что команда read выполняется в подоболочке и ее копия REPLY уничтожается по ее завершении.

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

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

<(список)

и для процессов, принимающих данные через стандартный ввод:

>(список)

где список — это список команд.

Ниже показано, как использовать подстановку процессов для решения проблемы с командой read:

read < <(echo "foo")

echo $REPLY

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

[me@linuxbox ~]$ echo <(echo "foo")

/dev/fd/63

Вывод результата подстановки командой echo показывает, что вывод подоболочки передается через файл с именем /dev/fd/63.

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