| |
| Advanced Bash-Scripting Guide: Искусство программирования на языке сценариев командной оболочки | ||
|---|---|---|
| Назад | Вперед | |
Встроенный документ (here document) является специальной формой перенаправления ввода/вывода, которая позволяет передать список команд интерактивной программе или команде, например ftp, telnet или ex. Конец встроенного документа выделяется "строкой-ограничителем", которая задается с помощью специальной последовательности символов <<. Эта последовательность -- есть перенаправление вывода из файла в программу, напоминает конструкцию interactive-program < command-file, где command-file содержит строки:
command #1 command #2 ...
Сценарий, использующий "встроенный документ" для тех же целей, может выглядеть примерно так:
#!/bin/bash interactive-program <<LimitString command #1 command #2 ... LimitString
В качестве строки-ограничителя должна выбираться такая последовательность символов, которая не будет встречаться в теле "встроенного документа".
Обратите внимание: использование встроенных документов может иногда с успехом применяться и при работе с неинтерактивными командами и утилитами.
Пример 17-1. dummyfile: Создание 2-х строчного файла-заготовки
#!/bin/bash # Неинтерактивное редактирование файла с помощью 'vi'. # Эмуляция 'sed'. E_BADARGS=65 if [ -z "$1" ] then echo "Порядок использования: `basename $0` filename" exit $E_BADARGS fi TARGETFILE=$1 # Вставить 2 строки в файл и сохранить. #--------Начало встроенного документа-----------# vi $TARGETFILE <<x23LimitStringx23 i Это строка 1. Это строка 2. ^[ ZZ x23LimitStringx23 #----------Конец встроенного документа-----------# # Обратите внимание: ^[, выше -- это escape-символ #+ Control-V <Esc>. # Bram Moolenaar указывает, что этот скрипт может не работать с 'vim', #+ из-за возможных проблем взаимодействия с терминалом. exit 0
Этот сценарий, с тем же эффектом, мог бы быть реализован, основываясь не на vi, а на ex. Встроенные документы, содержащие команды для ex, стали настолько обычным делом, что их уже смело можно вынести в отдельную категорию -- ex-сценарии.
Пример 17-2. broadcast: Передача сообщения всем, работающим в системе, пользователям
#!/bin/bash
wall <<zzz23EndOfMessagezzz23
Пошлите, по электронной почте, ваш заказ на пиццу, системному администратору.
(Добавьте дополнительный доллар, если вы желаете положить на пиццу анчоусы или грибы.)
# Внимание: строки комментария тоже будут переданы команде 'wall' как часть текста.
zzz23EndOfMessagezzz23
# Возможно, более эффективно это может быть сделано так:
# wall <message-file
# Однако, встроенный документ помогает сэкономить ваши силы и время.
exit 0
Пример 17-3. Вывод многострочных сообщений с помощью cat
#!/bin/bash # Команда 'echo' прекрасно справляется с выводом однострочных сообщений, # но иногда необходимо вывести несколько строк. # Команда 'cat' и встроенный документ помогут вам в этом. cat <<End-of-message ------------------------------------- Это первая строка сообщения. Это вторая строка сообщения. Это третья строка сообщения. Это четвертая строка сообщения. Это последняя строка сообщения. ------------------------------------- End-of-message exit 0 #-------------------------------------------- # Команда "exit 0", выше, не позволить исполнить нижележащие строки. # S.C. отмечает, что следующий код работает точно так же. echo "------------------------------------- Это первая строка сообщения. Это вторая строка сообщения. Это третья строка сообщения. Это четвертая строка сообщения. Это последняя строка сообщения. -------------------------------------" # Однако, в этом случае, двойные кавычки в теле сообщения, должны экранироваться.
Если строка-ограничитель встроенного документа начинается с символа - (<<-LimitString), то это приводит к подавлению вывода символов табуляции (но не пробелов). Это может оказаться полезным при форматировании текста сценария для большей удобочитаемости.
Пример 17-4. Вывод многострочных сообщений с подавлением символов табуляции
#!/bin/bash
# То же, что и предыдущий сценарий, но...
# Символ "-", начинающий строку-ограничитель встроенного документа: <<-
# подавляет вывод символов табуляции, которые могут встречаться в теле документа,
# но не пробелов.
cat <<-ENDOFMESSAGE
Это первая строка сообщения.
Это вторая строка сообщения.
Это третья строка сообщения.
Это четвертая строка сообщения.
Это последняя строка сообщения.
ENDOFMESSAGE
# Текст, выводимый сценарием, будет смещен влево.
# Ведущие символы табуляции не будут выводиться.
# Вышеприведенные 5 строк текста "сообщения" начинаются с табуляции, а не с пробелов.
exit 0
Встроенные документы поддерживают подстановку команд и параметров. Что позволяет передавать различные параметры в тело встроенного документа.
Пример 17-5. Встроенные документы и подстановка параметров
#!/bin/bash
# Вывод встроенного документа командой 'cat', с использованием подстановки параметров.
# Попробуйте запустить сценарий без аргументов, ./scriptname
# Попробуйте запустить сценарий с одним аргументом, ./scriptname Mortimer
# Попробуйте запустить сценарий с одним аргументом, из двух слов, в кавычках,
# ./scriptname "Mortimer Jones"
CMDLINEPARAM=1 # Минимальное число аргументов командной строки.
if [ $# -ge $CMDLINEPARAM ]
then
NAME=$1 # Если аргументов больше одного,
# то рассматривается только первый.
else
NAME="John Doe" # По-умолчанию, если сценарий запущен без аргументов.
fi
RESPONDENT="автора этого сценария"
cat <<Endofmessage
Привет, $NAME!
Примите поздравления от $RESPONDENT.
# Этот комментарий тоже выводится (почему?).
Endofmessage
# Обратите внимание на то, что пустые строки тоже выводятся.
exit 0
Заключая строку-ограничитель в кавычки или экранируя ее, можно запретить подстановку параметров в теле встроенного документа.
Пример 17-6. Отключение подстановки параметров
#!/bin/bash # Вывод встроенного документа командой 'cat', с запретом подстановки параметров. NAME="John Doe" RESPONDENT="автора этого сценария" cat <<'Endofmessage' Привет, $NAME. Примите поздравления от $RESPONDENT. Endofmessage # Подстановка параметров не производится, если строка ограничитель # заключена в кавычки или экранирована. # Тот же эффект дают: # cat <<"Endofmessage" # cat <<\Endofmessage exit 0
Еще один пример сценария, содержащего встроенный документ и подстановку параметров в его теле.
Пример 17-7. Передача пары файлов во входящий каталог на "Sunsite"
#!/bin/bash # upload.sh # Передача пары файлов (Filename.lsm, Filename.tar.gz) # на Sunsite (ibiblio.org). E_ARGERROR=65 if [ -z "$1" ] then echo "Порядок использования: `basename $0` filename" exit $E_ARGERROR fi Filename=`basename $1` # Отсечь имя файла от пути к нему. Server="ibiblio.org" Directory="/incoming/Linux" # Вообще, эти строки должны бы не "зашиваться" жестко в сценарий, # а приниматься в виде аргумента из командной строки. Password="your.e-mail.address" # Измените на свой. ftp -n $Server <<End-Of-Session # Ключ -n запрещает автоматическую регистрацию (auto-logon) user anonymous "$Password" binary bell # "Звякнуть" после передачи каждого файла cd $Directory put "$Filename.lsm" put "$Filename.tar.gz" bye End-Of-Session exit 0
Встроенные документы могут передаваться на вход функции, находящейся в том же сценарии.
Пример 17-8. Встроенные документы и функции
#!/bin/bash
# here-function.sh
GetPersonalData ()
{
read firstname
read lastname
read address
read city
read state
read zipcode
} # Это немного напоминает интерактивную функцию, но...
# Передать ввод в функцию.
GetPersonalData <<RECORD001
Bozo
Bozeman
2726 Nondescript Dr.
Baltimore
MD
21226
RECORD001
echo
echo "$firstname $lastname"
echo "$address"
echo "$city, $state $zipcode"
echo
exit 0
Встроенный документ можно передать "пустой команде" :. Такая конструкция, фактически, создает "анонимный" встроенный документ.
Пример 17-9. "Анонимный" Встроенный Документ
#!/bin/bash
: <<TESTVARIABLES
${HOSTNAME?}${USER?}${MAIL?} # Если одна из переменных не определена, то выводится сообщение об ошибке.
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-NAME\n" \ ; 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, который приспособлен для передачи параметров на вход интерактивных программ.
|
Закладки на сайте Проследить за страницей |
Created 1996-2025 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |