Поиск по сайту:

Учебное пособие по 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 с примерами

Статьи по данной тематике