Учебное пособие по Bash Heredoc для начинающих
При работе со сценариями Bash вы можете оказаться в ситуации, когда вам придется обрабатывать серию входных данных с помощью одной и той же команды. К счастью, в Bash есть способ добиться этого более оптимальным способом, используя HereDoc.
HereDoc, аббревиатура от Here Document, представляет собой метод перенаправления ввода для передачи нескольких входных данных в программу или команду. Концепция heredoc связана не только с Bash. Многие популярные языки программирования, такие как Perl, Ruby, PHP, поддерживают heredoc.
В этой статье мы рассмотрим синтаксис и использование heredoc в некоторых реальных случаях использования. Все примеры в этой статье созданы простыми, поэтому даже новичок сможет легко понять эту концепцию. Давайте приступим и начнем играть с heredoc в Bash.
ЗдесьDoc Синтаксис
Следующая диаграмма иллюстрирует синтаксис heredoc.
Графическая иллюстрация синтаксиса HereDoc
Здесь,
- Команда — любая команда (cat, wc, mail и т. д.), допускающая перенаправление.
- Оператор перенаправления (
<<
). Оператором по умолчанию для HereDoc является<<
. Он перенаправляет блок кода на команду для обработки. - Токен-разделитель. Токен-разделитель обозначает начало и конец документа (блока кода). Токен-разделитель может быть любым, но он должен быть идентичным. Обычно вы увидите, что
EOF
используется в качестве токенов-разделителей, что означает «Конец файлового потока».
Печать многострочной строки с использованием HereDoc в Bash
Начнем с простого примера перенаправления многострочной строки и ее вывода на терминал.
Команда cat
принимает поток входных данных с помощью heredoc, и вы можете перенаправить блок кода для печати его на терминал.
$ cat << EOF
Something is wrong with the input file received for today.
Contact the downstream team to get it corrected.
==> SLA MISSED <==
EOF
Выход:
Something is wrong with the input file received for today.
Contact the downstream team to get it corrected.
==> SLA MISSED <==
Взгляните на приведенный выше фрагмент кода. У меня есть три строки, которые перенаправляются на команду cat
. Я использую EOF
в качестве разделителя. Однако вы можете использовать что угодно, но сохраняйте одинаковый начальный и конечный разделитель.
Давайте попробуем еще на одном простом примере. Я перенаправляю ту же трехстрочную строку в программу word count. Здесь я использую другой разделитель (BLK
).
$ wc -l << BLK
Something is wrong with the input file received for today.
Contact the downstream team to get it corrected.
==> SLA MISSED <==
BLK
Пример вывода:
3
Печать многострочной строки с использованием heredoc
Перенаправление и передача в HereDoc
Вы можете объединить оператор перенаправления вывода с heredoc и перенаправить вывод в файл вместо того, чтобы печатать его на терминал.
Я использую тот же пример, что и в предыдущем разделе, и перенаправляю вывод в файл с именем log_op.txt
.
$ cat << EOF > /tmp/log_op.txt
Something is wrong with the input file received for today.
Contact the downstream team to get it corrected.
==> SLA MISSED <==
EOF
Вывод heredoc можно отправить оператору pipe для дальнейшей обработки.
$ cat << EOF | grep -i sla
Something is wrong with the input file received for today.
Contact the downstream team to get it corrected.
==> SLA MISSED <==
EOF
Подавление вкладок в HereDoc
Если в блоке кода есть пробелы (табуляции) и вы хотите их подавить, используйте "-"
после оператора перенаправления. Важным моментом, который следует отметить, является то, что будут подавляться только табуляции, а не пробелы.
Взгляните на приведенный ниже пример. Я добавил условный оператор к тому же примеру, который мы видели в предыдущих разделах. Первые две строки в heredoc разделены табуляцией (4), а третья строка разделена интервалом (2).
if [[ $x = "err" ]]
then
cat <<- err_msg
1. Something is wrong with the input file received for today.
2. Contact the downstream team to get it corrected.
3. ==> SLA MISSED <==
err_msg
fi
Когда фрагмент кода будет отправлен, мой результат будет следующим.
1. Something is wrong with the input file received for today.
2. Contact the downstream team to get it corrected.
3. ==> SLA MISSED <==
Как видите, табуляция в строках 1 и 2 отключена, но в строке 3, поскольку используются пробелы, она не подавляется.
Расширение переменных и команд в HereDoc
Это не значит, что в блоке кода heredoc можно передавать только строки. Вы можете передавать определяемые пользователем переменные и переменные среды, а также запускать команды внутри блока кода.
Взгляните на приведенный ниже пример. Внутри блока кода у меня есть одна определяемая пользователем переменная "$ {AUTHOR}"
, одна переменная среды "$ {SHELL}"
, внешняя команда "Вьюми"
.
Когда этот фрагмент будет отправлен, переменные и команды будут развернуты, а затем будут перенаправлены на команду cat
.
AUTHOR="OSTechNix"
cat << EOF
Author: ${AUTHOR} # USER DEFINED VARIABLE
Article: Bash Heredoc
I am using the ${SHELL} shell # ENV VARIABLE
$(whoami) # EXTERNAL COMMAND
EOF
Пример вывода:
Author: OsTechnix
Article: Bash Heredoc
I am using the /bin/bash shell
karthick
Вы можете заключить начальный разделитель в одинарные кавычки, чтобы подавить расширение внутри блока кода. Таким образом, все внутри блока кода будет рассматриваться как строковый литерал.
cat << 'EOF'
Author: ${AUTHOR} # USER DEFINED VARIABLE
Article: Bash Heredoc
I am using the ${SHELL} shell # ENV VARIABLE
$(whoami) # EXTERNAL COMMAND
EOF
Пример вывода:
Author: ${AUTHOR}
Article: Bash Heredoc
I am using the ${SHELL} shell
$(whoami)
Многострочные комментарии с помощью HereDoc
Как вы, возможно, уже знаете, Bash не поддерживает многострочные комментарии. Используя heredoc, вы можете создавать многострочные комментарии, перенаправляя блок кода на команду no-op
(:
).
no-op
— это встроенная функция bash, которая принимает входные данные и возвращает нулевой код выхода. Вы можете рассматривать это как синоним встроенного в bash "true", который также завершает нулевой код выхода.
: << 'COMMENTS'
Author : OStechnix
Article : Bash Heredoc
BashV : 5.1.4
OS : PoP!_OS
COMMENTS
Внимание! Почти каждый текстовый редактор имеет функцию выделения нескольких строк и позволяет комментировать или удалять комментарии с помощью нажатия клавиши. Лучше придерживаться этого подхода.
Экранирование специальных символов в HereDoc
Блоки кода могут содержать специальные символы. Если вы хотите избежать использования специальных символов, есть несколько способов сделать это.
Вы можете заключить разделитель в одинарные или двойные кавычки или префикс обратной косой черты с разделителем. Таким образом, все специальные символы будут экранированы.
# SINGLE QUOTES ESCAPE
cat << 'EOF'
I am using the ${SHELL} shell # ENV VARIABLE
$(whoami) # EXTERNAL COMMAND
EOF
# DOUBLE QUOTES ESCAPE
cat << "EOF"
I am using the ${SHELL} shell # ENV VARIABLE
$(whoami) # EXTERNAL COMMAND
EOF
# BACKSLASH ESCAPE
cat << \EOF
I am using the ${SHELL} shell # ENV VARIABLE
$(whoami) # EXTERNAL COMMAND
EOF
Вместо экранирования всех специальных символов вы также можете экранировать отдельные специальные символы внутри блока, добавив обратную косую черту перед любым специальным символом.
cat << EOF
I am using the \${SHELL} shell # ENV VARIABLE
$(whoami) # EXTERNAL COMMAND
EOF
Пример вывода:
I am using the ${SHELL} shell
karthick
Вариант использования здесьDoc
До сих пор мы видели основную конструкцию heredoc и ее базовое использование. Теперь давайте посмотрим несколько реальных случаев использования. По моему опыту, я использовал heredoc при работе с ssh и клиентами баз данных, где мне приходилось запускать группу команд.
Пример 1: запуск скрипта от имени другого пользователя
В некоторых случаях вам может потребоваться запустить определенные части вашего кода от имени другого пользователя. В этом случае вы можете использовать heredoc для перенаправления команд для запуска от имени другого пользователя.
Взгляните на приведенный ниже пример. Я перенаправляю блок кода на команду su
, которая переключит пользователя на "ostechnix" и создаст файл с именем test, если он не существует.
su - ostechnix << EOF
if [[ ! -f /home/ostechnix/test ]];then
touch /home/ostechnix/test
echo "File Created"
else
echo "File exists"
fi
EOF
HereDoc с другим пользователем
Пример 2. Использование HereDoc с клиентом БД
Если вы хотите выполнить серию команд для базы данных, вам пригодится heredoc.
Взгляните на приведенный ниже пример. Я взаимодействую с клиентом MongoDB mongosh, и внутри heredoc передаются команды блока кода для создания новой базы данных, коллекции и добавления образца документа.
mongosh << EOF
use ostechnix
db.data.insertOne({
"Site" : "OsTechnix",
"DB" : "Mongo"
})
db.data.find().pretty()
EOF
HereDoc с клиентом MongoDB
Вы можете знать или не знать MongoDB, но это нормально. Это просто для того, чтобы показать, как использовать heredoc для взаимодействия с клиентами БД. Вы можете использовать любой клиент базы данных, например MySQL, psql, sqlite, в зависимости от того, с какой базой данных вы работаете.
Пример 3. Выполнение удаленных команд с помощью HereDoc и SSH.
Если вы хотите запускать команды через удаленный сервер, вы можете использовать heredoc в сочетании с командой ssh
. Обычно с помощью команды ssh
вы можете запускать команды на удаленном сервере следующим образом.
ssh user@host "command"
Вам придется повторять одну и ту же команду снова и снова, если вы хотите запустить больше команд на удаленном хосте. С помощью heredoc вы можете группировать все команды и запускать их.
ssh -T user@host << EOF
Command 1...
Command 2..
.....
Command N..
EOF
Если один и тот же код необходимо выполнить на нескольких узлах, вы можете добавить цикл for
вместе с heredoc. Я использую тот же фрагмент создания файла, который мы видели в первом примере.
- Переменная массива «server» содержит список имен серверов.
- Цикл for перебирает переменную массива.
- Команда создания файла передается команде SSH, которая будет перебирать и создавать файлы на каждом сервере. Обязательно добавьте флаг
-T
в команду ssh, который отключит выделение псевдотерминала.
declare -a server=( host1 host2 host3 )
for host in ${server[@]}
do
ssh -T user@${host} << EOF
echo "Running at host - ${host}"
if [[ ! -f /home/ostechnix/test ]];then
touch /home/ostechnix/test
echo "File Created"
else
echo "File exists"
fi
EOF
done
Заключение
Heredoc — это важная концепция, которую нужно понимать и использовать в сценариях Bash. Когда вы напишете много скриптов, вы узнаете больше о heredoc и способах его оптимального использования.
Если вы никогда раньше не использовали heredoc, запустите терминал и попробуйте все фрагменты кода из статьи, чтобы лучше понять.
Связанное чтение:
- Скрипты Bash: переменные, поясняемые примерами
- Скрипты Bash: функции, поясняемые примерами
- Команда Bash Echo с примерами для Linux
- Скрипты Bash: цикл For с примерами
- Скрипты Bash: циклы while и Until с примерами