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

Как использовать Heredoc в сценариях оболочки


Здесь документ (Heredoc) — это литерал ввода или файлового потока, который рассматривается как специальный блок кода. Этот блок кода будет передан команде на обработку. Heredoc происходит из оболочек UNIX и может быть найден в популярных оболочках Linux, таких как sh, tcsh, ksh, bash, zsh, csh. Примечательно, что другие языки программирования, такие как Perl, Ruby, PHP, также поддерживают heredoc.

Структура Хердока

Heredoc использует две угловые скобки (<<), за которыми следует токен-разделитель. Тот же токен-разделитель будет использоваться для завершения блока кода. Все, что попадает в разделитель, считается блоком кода.

Посмотрите на пример ниже. Я перенаправляю блок кода на команду cat. Здесь разделитель установлен на «BLOCK» и заканчивается тем же «BLOCK».

cat << BLOCK
	Hello world
	Today date is $(date +%F)
	My home directory = ${HOME}
BLOCK

ПРИМЕЧАНИЕ. Для запуска и завершения блока следует использовать один и тот же токен-разделитель.

Создание многострочных комментариев

Если вы сейчас пишете код на bash, вы, возможно, знаете, что bash по умолчанию не поддерживает многострочные комментарии, такие как C или Java. Чтобы обойти эту проблему, вы можете использовать HereDoc.

Это не встроенная функция bash, поддерживающая многострочные комментарии, а просто хак. Если вы не перенаправляете heredoc на какую-либо команду, интерпретатор просто прочитает блок кода и ничего не выполнит.

<< COMMENT
	This is comment line 1
	This is comment line 2
	This is comment line 3
COMMENT

Обработка пробелов

По умолчанию heredoc не подавляет пробелы (табуляции, пробелы). Мы можем переопределить это поведение, добавив тире (-) после (<<), за которым следует разделитель. Это приведет к подавлению всех пробелов табуляции, но пробелы не будут подавлены.

cat <<- BLOCK
This line has no whitespace.
  This line has 2 white spaces at the beginning.
    This line has a single tab.
        This line has 2 tabs.
            This line has 3 tabs.
BLOCK

Замена переменных и команд

Heredoc допускает замену переменных. Переменные могут быть определяемыми пользователем переменными или переменными среды.

TODAY=$(date +%F)
	
cat << BLOCK1
User defined variables
Today date is = ${TODAY}
#Environ Variables
I am running as = ${USER}
My home dir is = ${HOME}
I am using ${SHELL} as my shell
BLOCK1

Аналогичным образом вы можете запускать любые команды внутри блока кода heredoc.

cat << BLOCK2
$(uname -a) 
BLOCK2

Экранирование специальных символов

Есть несколько способов избежать специальных символов. Либо вы можете сделать это на уровне персонажа или уровня документа.

Чтобы экранировать отдельные специальные символы, используйте обратную косую черту (\).

cat << BLOCK4
$(uname -a)
BLOCK4

cat << BLOCK5
Today date is = ${TODAY}
BLOCK5

Чтобы экранировать все специальные символы внутри блока, заключите разделитель в одинарные или двойные кавычки или разделитель префикса с обратной косой чертой.

cat << 'BLOCK1'
I am running as = ${USER}
BLOCK1

cat << "BLOCK2"
I am running as = ${USER}
BLOCK2

cat << \BLOCK3
I am running as = ${USER}
BLOCK3

Теперь, когда мы знаем структуру heredoc и как она работает, давайте рассмотрим несколько примеров. Две распространенные области, в которых я использую heredoc, — это выполнение блока команд через SSH и передача SQL-запросов через heredoc.

В приведенном ниже примере мы пытаемся выполнить блок кода на удаленном сервере через SSH.

В приведенном ниже примере я передаю оператор select в psql для подключения к базе данных и выполнения запроса. Это альтернативный способ запуска запроса в psql внутри сценария bash вместо использования флага -f для запуска файла .sql.

#!/usr/bin/env bash

UNAME=postgres
DBNAME=testing

psql --username=${UNAME} --password --dbname=${DBNAME} << BLOCK
SELECT * FROM COUNTRIES
WHERE region_id = 4;
BLOCK

Вот и все, что касается этой статьи. С помощью heredoc вы можете сделать гораздо больше по сравнению с тем, что мы показали в примерах. Если у вас есть какой-нибудь полезный хак для heredoc, опубликуйте его в разделе комментариев, чтобы наши читатели могли извлечь из этого пользу.