Мендель Купер - Искусство программирования на языке сценариев командной оболочки
# Чтение строк из файла /etc/fstab.
File=/etc/fstab
{
read line1
read line2
} < $File
echo "Первая строка в $File :"
echo "$line1"
echo
echo "Вторая строка в $File :"
echo "$line2"
exit 0
Пример 3-2. Сохранение результата исполнения вложенного блока в файл
#!/bin/bash
# rpm-check.sh
# Запрашивает описание rpm-архива, список файлов, и проверяется возможность установки.
# Результат сохраняется в файле.
#
# Этот сценарий иллюстрирует порядок работы со вложенными блоками кода.
SUCCESS=0
E_NOARGS=65
if [ -z "$1" ]
then
echo "Порядок использования: `basename $0` rpm-file"
exit $E_NOARGS
fi
{
echo
echo "Описание архива:"
rpm -qpi $1 # Запрос описания.
echo
echo "Список файлов:"
rpm -qpl $1 # Запрос списка.
echo
rpm -i --test $1 # Проверка возможности установки.
if [ "$?" -eq $SUCCESS ]
then
echo "$1 может быть установлен."
else
echo "$1 -- установка невозможна!"
fi
echo
} > "$1.test" # Перенаправление вывода в файл.
echo "Результаты проверки rpm-архива находятся в файле $1.test"
# За дополнительной информацией по ключам команды rpm см. man rpm.
exit 0
В отличие от групп команд в (круглых скобках), описаных выше, вложенные блоки кода, заключенные в {фигурные скобки} исполняются в пределах того же процесса, что и сам скрипт (т.е. не вызывают запуск дочернего процесса -- subshell).[ 12 ]
{} ;
pathname -- полное имя файла (т.е. путь к файлу и его имя). Чаще всего используется совместно с командой find.
Обратите внимание на то, что символ ";", которым завершается ключ -exec команды find, экранируется обратным слэшем. Это необходимо, чтобы предотвратить его интерпретацию.
[ ]
test.
Проверка истинности выражения, заключенного в квадратные скобки [ ]. Примечательно, что [ является частью встроенной команды test (и ее синонимом), И не имеет никакого отношения к "внешней" утилите /usr/bin/test.
[[ ]]
test.
Проверка истинности выражения, заключенного между [[ ]] (зарезервированное слово интерпретатора).
См. описание конструкции [[ ... ]] ниже.
[ ]
элемент массива.
При работе с массивами в квадратных скобках указывается порядковый номер того элемента массива, к которому производится обращение.
Array[1]=slot_1
echo ${Array[1]}
[ ]
диапазон символов.
В регулярных выражениях, в квадратных скобках задается диапазон искомых символов.
(( ))
двойные круглые скобки.
Вычисляется целочисленное выражение, заключенное между двойными круглыми скобками (( )).
См. обсуждение, посвященное конструкции (( ... )) .
> &> >& >> <
перенаправление.
Конструкция scriptname >filename перенаправляет вывод scriptname в файл filename. Если файл filename уже существовал, то его прежнее содержимое будет утеряно.
Конструкция command &>filename перенаправляет вывод команды command, как со stdout, так и с stderr, в файл filename.
Конструкция command >&2 перенаправляет вывод со stdout на stderr.
Конструкция scriptname >>filename добавляет вывод scriptname к файлу filename. Если задано имя несуществующего файла, то он создается.
подстановка процесса.
(command)>
<(command)
В операциях сравнения, символы "<" и ">" обозначают операции сравнения строк .
А так же -- операции сравнения целых чисел. См. так же Пример 12-6.
<<
перенаправление ввода на встроенный документ.
<, >
Посимвольное ASCII-сравнение.
veg1=carrots
veg2=tomatoes
if [[ "$veg1" < "$veg2" ]]
then
echo "Не смотря на то, что в словаре слово $veg1 предшествует слову $veg2,"
echo "это никак не отражает мои кулинарные предпочтения."
else
echo "Интересно. Каким словарем вы пользуетесь?"
fi
<, >
границы отдельных слов в регулярных выражениях.
bash$ grep '<the>' textfile
|
конвейер. Передает вывод предыдущей команды на ввод следующей или на вход командного интерпретатора shell. Этот метод часто используется для связывания последовательности команд в единую цепочку.
echo ls -l | sh
# Передает вывод "echo ls -l" команлному интерпретатору shell,
#+ тот же результат дает простая команда "ls -l".
cat *.lst | sort | uniq
# Объединяет все файлы ".lst", сортирует содержимое и удаляет повторяющиеся строки.
Конвейеры (еще их называют каналами) -- это классический способ взаимодействия процессов, с помощью которого stdout одного процесса перенаправляется на stdin другого. Обычно используется совместно с командами вывода, такими как cat или echo, от которых поток данных поступает в "фильтр" (команда, которая на входе получает данные, преобразует их и обрабатывает).
cat $filename | grep $search_word
В конвейер могут объединяться и сценарии на языке командной оболочки.
#!/bin/bash
# uppercase.sh : Преобразование вводимых символов в верхний регистр.
tr 'a-z' 'A-Z'
# Диапазоны символов должны быть заключены в кавычки
#+ чтобы предотвратить порождение имен файлов от однобуквенных имен файлов.
exit 0
А теперь попробуем объединить в конвейер команду ls -l с этим сценарием.
bash$ ls -l | ./uppercase.sh
-RW-RW-R-- 1 BOZO BOZO 109 APR 7 19:49 1.TXT
-RW-RW-R-- 1 BOZO BOZO 109 APR 14 16:48 2.TXT
-RW-R--R-- 1 BOZO BOZO 725 APR 20 20:56 DATA-FILE
Выход stdout каждого процесса в конвейере должен читаться на входе stdin последующим, в конвейере, процессом. Если этого не делается, то поток данных блокируется, в результате конвейер будет работать не так как ожидается.
cat file1 file2 | ls -l | sort
# Вывод команды "cat file1 file2" будет утерян.
Конвейер исполняется в дочернем процессе, а посему -- не имеет доступа к переменным сценария.
variable="initial_value"
echo "new_value" | read variable
echo "variable = $variable" # variable = initial_value
Если одна из команд в конвейере завершается аварийно, то это приводит к аварийному завершению работы всего конвейера.
>|
принудительное перенаправление, даже если установлен ключ noclobber option.
||
логическая операция OR (логическое ИЛИ). В опрециях проверки условий, оператор || возвращает 0 (success), если один из операндов имеет значение true (ИСТИНА).
&
Выполнение задачи в фоне. Команда, за которой стоит &, будет исполняться в фоновом режиме.
bash$ sleep 10 &
[1] 850
[1]+ Done sleep 10
В сценариях команды, и даже циклы могут запускаться в фоновом режиме.
Пример 3-3. Запуск цикла в фоновом режиме
#!/bin/bash
# background-loop.sh
for i in 1 2 3 4 5 6 7 8 9 10 # Первый цикл.
do
echo -n "$i "
done & # Запуск цикла в фоне.
# Иногда возможны случаи выполнения этого цикла после второго цикла.
echo # Этот 'echo' иногда не отображается на экране.
for i in 11 12 13 14 15 16 17 18 19 20 # Второй цикл.
do
echo -n "$i "
done
echo # Этот 'echo' иногда не отображается на экране.
# ======================================================
# Ожидается, что данный сценарий выведет следующую последовательность:
# 1 2 3 4 5 6 7 8 9 10
# 11 12 13 14 15 16 17 18 19 20
# Иногда возможен такой вариант:
# 11 12 13 14 15 16 17 18 19 20
# 1 2 3 4 5 6 7 8 9 10 bozo $
# (Второй 'echo' не был выполнен. Почему?)
# Изредка возможен такой вариант:
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# (Первый 'echo' не был выполнен. Почему?)