Мендель Купер - Искусство программирования на языке сценариев командной оболочки
TESTVARIABLES
exit 0
Подобную технику можно использовать для создания "блочных комментариев".
Пример 17-10. Блочный комментарий
#!/bin/bash
# commentblock.sh
: << COMMENTBLOCK
echo "Эта строка не будет выведена."
Эта строка комментария не начинается с символа "#".
Это еще одна строка комментария, которая начинается не с символа "#".
&*@!!++=
Эта строка не вызовет ошибки,
поскольку Bash проигнорирует ее.
COMMENTBLOCK
echo "Код завершения "COMMENTBLOCK" = $?." # 0
# Показывает, что ошибок не возникало.
# Такая методика создания блочных комментариев
#+ может использоваться для комментирования блоков кода во время отладки.
# Это экономит силы и время, т.к. не нужно втавлять символ "#" в начале каждой строки,
#+ а затем удалять их.
: << DEBUGXXX
for file in *
do
cat "$file"
done
DEBUGXXX
exit 0
Еще одно остроумное применение встроенных документов -- встроенная справка к сценарию.
Пример 17-11. Встроенная справка к сценарию
#!/bin/bash
# self-document.sh: сценарий со встроенной справкой
# Модификация сценария "colm.sh".
DOC_REQUEST=70
if [ "$1" = "-h" -o "$1" = "--help" ] # Request help.
then
echo; echo "Порядок использования: $0 [directory-name]"; echo
sed --silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATION/p' "$0" |
sed -e '/DOCUMENTATIONXX/d'; exit $DOC_REQUEST; fi
: << DOCUMENTATIONXX
Сценарий выводит сведения о заданном каталоге в виде таблице.
-------------------------------------------------------------
Сценарию необходимо передать имя каталога. Если каталог не
указан или он недоступен для чтения, то выводятся сведения
о текущем каталоге.
DOCUMENTATIONXX
if [ -z "$1" -o ! -r "$1" ]
then
directory=.
else
directory="$1"
fi
echo "Сведения о каталоге "$directory":"; echo
(printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAMEn"
; ls -l "$directory" | sed 1d) | column -t
exit 0
Для встроенных документов, во время исполнения, создаются временные файлы, но эти файлы удаляются после открытия и недоступны для других процессов.
bash$ bash -c 'lsof -a -p $$ -d0' << EOF
> EOF
lsof 1213 bozo 0r REG 3,5 0 30386 /tmp/t1213-0-sh (deleted)
Некоторые утилиты не могут работать внутри встроенных документов.
Если какая либо задача не может быть решена с помощью "встроенного документа", то вам следует попробовать язык сценариев expect, который приспособлен для передачи параметров на вход интерактивных программ.
Часть 4. Материал повышенной сложности
Итак, мы вплотную подошли к изучению очень сложных и необычных аспектов написания сценариев. В этой части мы попытаемся "сбросить покров тайны" и заглянуть за пределы известного нам мира (представьте себе путешествие по территории, не отмеченной на карте).
Глава 18. Регулярные выражения
Для того, чтобы полностью реализовать потенциал командной оболочки, вам придется овладеть Регулярными Выражениями. Многие команды и утилиты, обычно используемые в сценариях, такие как grep, expr, sed и awk, используют Регулярные Выражения.
18.1. Краткое введение в регулярные выражения
Выражение -- это строка символов. Символы, которые имеют особое назначение, называются метасимволами. Так, например, кавычки могут выделять прямую речь, т.е. быть метасимволами для строки, заключенной в эти кавычки. Регулярные выражения -- это набор символов и/или метасимволов, которые наделены особыми свойствами[ 46 ].
Основное назначение регулярных выражений -- это поиск текста по шаблону и работа со строками.
Звездочка -- * -- означает любое количество символов в строке, предшествующих "звездочке", в том числе и нулевое число символов.
Выражение "1133*" -- означает 11 + один или более символов "3" + любые другие символы: 113, 1133, 113312, и так далее.
Точка -- . -- означает не менее одного любого символа, за исключением символа перевода строки (n)[ 47 ].
Выражение "13." будет означать 13 + по меньшей мере один любой символ (включая пробел): 1133, 11333, но не 13 (отсутствуют дополнительные символы).
Символ -- ^ -- означает начало строки, но иногда, в зависимости от контекста, означает отрицание в регулярных выражениях.
Знак доллара -- $ -- в конце регулярного выражения соответствует концу строки.
Выражение "^$" соответствует пустой строке.
Символы ^ и $ иногда еще называют якорями, поскольку они означают, или закрепляют, позицию в регулярных выражениях.
Квадратные скобки -- [...] -- предназначены для задания подмножества символов. Квадратные скобки, внутри регулярного выражения, считаются одним символом, который может принимать значения, перечисленные внутри этих скобок..
Выражение "[xyz]" -- соответствует одному из символов x, y или z.
Выражение "[c-n]" соответствует одному из символов в диапазоне от c до n, включительно.
Выражение "[B-Pk-y]" соответствует одному из символов в диапазоне от B до P или в диапазоне от k до y, включительно.
Выражение "[a-z0-9]" соответствует одному из символов латиницы в нижнем регистре или цифре.
Выражение "[^b-d]" соответствует любому символу, кроме символов из диапазона от b до d, включительно. В данном случае, метасимвол ^ означает отрицание.
Объединяя квадратные скобки в одну последовательность, можно задать шаблон искомого слова. Так, выражение "[Yy][Ee][Ss]" соответствует словам yes, Yes, YES, yEs и так далее. Выражение "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]" определяет шаблон для поиска любого номера карточки социального страхования (для США).
Обратный слэш -- -- служит для экранирования специальных символов, это означает, что экранированные символы должны интерпретироваться буквально, т.е. как простые символы.
Комбинация "$" указывает на то, что символ "$" трактуется как обычный символ, а не как признак конца строки в регулярных выражениях. Аналогично, комбинация "\" соответствует простому символу "".
Экранированные "угловые скобки" -- <...> -- отмечают границы слова.
Угловые скобки должны экранироваться, иначе они будут интерпретироваться как простые символы.
Выражение "<the>" соответствует слову "the", и не соответствует словам "them", "there", "other" и т.п.
bash$ cat textfile
This is line 1, of which there is only one instance.
This is the only instance of line 2.
This is line 3, another line.
This is line 4.
bash$ grep 'the' textfile
This is line 1, of which there is only one instance.
This is the only instance of line 2.
This is line 3, another line.
bash$ grep '<the>' textfile
This is the only instance of line 2.
Дополнительные метасимволы. Использующиеся при работе с egrep, awk и Perl
Знак вопроса -- ? -- означает, что предыдущий символ или регулярное выражение встречается 0 или 1 раз. В основном используется для поиска одиночных символов.
Знак "плюс" -- + -- указывает на то, что предыдущий символ или выражение встречается 1 или более раз. Играет ту же роль, что и символ "звездочка" (*), за исключением случая нулевого количества вхождений.
# GNU версии sed и awk допускают использование "+",
# но его необходимо экранировать.
echo a111b | sed -ne '/a1+b/p'
echo a111b | grep 'a1+b'
echo a111b | gawk '/a1+b/'
# Все три варианта эквивалентны.
# Спасибо S.C.
Экранированные "фигурные скобки" -- { } -- задают число вхождений предыдущего выражения.
Экранирование фигурных скобок -- обязательное условие, иначе они будут интерпретироваться как простые символы. Такой порядок использования, технически, не является частью основного набора правил построения регулярных выражений.
Выражение "[0-9]{5}" -- в точности соответствует подстроке из пяти десятичных цифр (символов из диапазона от 0 до 9, включительно).
В "классической" (не совместимой с POSIX) версии awk, фигурные скобки не могут быть использованы. Однако, в gawk предусмотрен ключ --re-interval, который позволяет использовать (неэкранированные) фигурные скобки.
bash$ echo 2222 | gawk --re-interval '/2{3}/'
2222
Язык программирования Perl и некоторые версии egrep не требуют экранирования фигурных скобок.
Круглые скобки -- ( ) -- предназначены для выделения групп регулярных выражений. Они полезны при использовании с оператором "|" и при извлечении подстроки с помощью команды expr.
Вертикальная черта -- | -- выполняет роль логического оператора "ИЛИ" в регулярных выражениях и служит для задания набора альтернатив.
bash$ egrep 're(a|e)d' misc.txt
People who read seem to be better informed than those who do not.