Литмир - Электронная Библиотека
Содержание  
A
A

[me@linuxbox ~]$ echo ${foo[@]}

a b c d e f

[me@linuxbox ~]$ unset foo

[me@linuxbox ~]$ echo ${foo[@]}

[me@linuxbox ~]$

Командой unset можно также удалить единственный элемент массива:

[me@linuxbox ~]$ foo=(a b c d e f)

[me@linuxbox ~]$ echo ${foo[@]}

a b c d e f

[me@linuxbox ~]$ unset 'foo[2]'

[me@linuxbox ~]$ echo ${foo[@]}

a b d e f

В этом примере мы удалили третий элемент массива, с индексом 2. Не забывайте, что индексация элементов массива начинается с 0, а не с 1! Отметьте также, что элемент массива нужно заключить в кавычки, чтобы предотвратить подстановку путей оболочкой.

Интересно отметить, что присваивание пустого значения массиву не уничтожает его содержимое:

[me@linuxbox ~]$ foo=(a b c d e f)

[me@linuxbox ~]$ foo=

[me@linuxbox ~]$ echo ${foo[@]}

b c d e f

Любая ссылка на переменную-массив без индекса возвращает элемент с индексом 0:

[me@linuxbox ~]$ foo=(a b c d e f)

[me@linuxbox ~]$ echo ${foo[@]}

a b c d e f

[me@linuxbox ~]$ foo=A

[me@linuxbox ~]$ echo ${foo[@]}

A b c d e f

Заключительное замечание

Если на странице справочного руководства (man) для bash выполнить поиск слова array, можно найти множество его упоминаний, где описываются приемы работы с переменными-массивами. Большая часть этих описаний довольно туманна, но иногда они содержат весьма полезные сведения. Фактически массивы недостаточно широко используются в программировании на языке командной оболочки, в основном потому, что традиционные командные оболочки для Unix (такие, как sh) не поддерживают их. Об этом недостатке остается только сожалеть, потому что массивы очень популярны в других языках программирования и являются мощным инструментом, позволяющим решать многие задачи программирования.

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

for ((выражение1; выражение2; выражение3))

36. Экзотика

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

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

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 в цикле, обрабатывающем список файлов в каталоге, созданном подоболочкой:

#!/bin/bash

# pro-sub : демонстрация подстановки процессов

while read attr links owner group size date time filename; do

        cat <<- EOF

                Filename:   $filename

                Size:       $size

                Owner:      $owner

                Group:      $group

111
{"b":"568756","o":1}