Другое

Понимание синтаксиса cat << EOF в Bash

Узнайте, как синтаксис cat << EOF создает here documents в bash для перенаправления многострочного ввода. Полное руководство с примерами для SQL-команд и скриптинга.

Как работает синтаксис ‘cat << EOF’ в bash?

Мне нужно было написать скрипт для ввода многострочных данных в программу (psql). После некоторых исследований я обнаружил, что следующий синтаксис работает:

bash
cat << EOF | psql ---params
BEGIN;

pg_dump ----something

update table .... statement ...;

END;
EOF

Это правильно создает многострочную строку (от BEGIN; до END;, включительно) и передает ее как ввод в psql. Однако я не понимаю, как и почему это работает.

Я в основном имею в виду часть ‘cat << EOF’. Я знаю, что ‘>’ выводит в файл, ‘>>’ добавляет в файл, а ‘<’ читает ввод из файла. Что именно делает оператор ‘<<’?

Существует ли страница руководства (man page), которая объясняет этот синтаксис?

Синтаксис cat << EOF в bash создает here document (herедоку), который перенаправляет несколько строк текста в качестве входных данных для команды cat. Оператор << указывает bash читать все между открывающим << EOF и закрывающим разделителем EOF как стандартный ввод для команды, что позволяет создавать многострочные строки непосредственно в вашем скрипте.

Содержание

Что такое heredoc?

Here document (heredoc) - это метод перенаправления в оболочке, который позволяет передавать несколько строк текста команде. Оператор << делает это возможным. В отличие от обычного перенаправления (>, >>, <), которое работает с файлами, heredoc работает с буквальным текстом, встроенным в ваш скрипт.

bash
cat << EOF
Это строка первая
Это строка вторая
Это строка третья
EOF

В этом примере текст между << EOF и EOF становится входными данными для команды cat, которая затем выводит их в стандартный вывод.

Как работает оператор <<

Оператор << - это оператор перенаправления в оболочке, который указывает bash:

  1. Читать строки из скрипта до тех пор, пока не встретит слово-разделитель (EOF в вашем случае)
  2. Рассматривать все эти строки как стандартный ввод для предыдущей команды (cat)
  3. Продолжить обработку скрипта нормально после строки с разделителем

Ключевое понимание заключается в том, что << создает временный поток ввода из текста, следующего в скрипте, а не из файла или ввода пользователя.

Разбор синтаксиса

Давайте разберем ваш пример:

bash
cat << EOF | psql ---params
BEGIN;

pg_dump ----something

update table .... statement ...;

END;
EOF
  • cat: Команда, которая получает входные данные
  • << EOF: Открывает heredoc с EOF в качестве разделителя
  • Многострочное содержимое: Текст, который становится входными данными для cat
  • EOF: Разделитель, завершающий heredoc (должен стоять в отдельной строке)
  • | psql ---params: Передает вывод из cat в psql через канал

Heredoc создает временный поток ввода для cat, который затем передает это содержимое в psql через канал.

Практические примеры

Базовое использование heredoc

bash
# Простой текстовый вывод
cat << EOF
Hello, World!
This is a test.
EOF

# Вывод:
# Hello, World!
# This is a test.

Heredoc с переменными

bash
name="John"
age=25

cat << EOF
My name is $name
I am $age years old
EOF

# Вывод:
# My name is John
# I am 25 years old

Heredoc в вашем примере с psql

Ваше использование идеально подходит для SQL-команд, которые должны выполняться как одна транзакция:

bash
cat << EOF | psql -d mydatabase
BEGIN;

-- Создаем резервную копию
pg_dump -t my_table > backup.sql

-- Обновляем некоторые данные
UPDATE users SET status = 'active' WHERE created_at > '2024-01-01';

-- Завершаем транзакцию
COMMIT;
EOF

Расширенные возможности heredoc

Подстановка переменных

По умолчанию, heredoc выполняет подстановку переменных:

bash
#!/bin/bash
DB_NAME="production"
TABLE_NAME="users"

cat << EOF
Connecting to database: $DB_NAME
Processing table: $TABLE_NAME
EOF

Кавычки для отключения подстановки

Вы можете отключить подстановку переменных, заключив разделитель в кавычки:

bash
#!/bin/bash
DB_NAME="production"

cat << 'EOF'
Database name: $DB_NAME
EOF

# Вывод:
# Database name: $DB_NAME

Отступы в heredoc

Вы можете добавить отступы к содержимому heredoc, если используете <<- (обратите внимание на тире):

bash
#!/bin/bash
if true; then
    cat <<- EOF
    This is indented
    But will be output
    Without the leading spaces
    EOF
fi

Heredoc с разными разделителями

Разделитель не обязательно должен быть EOF - это может быть любое слово:

bash
cat << SQL_MARKER
SELECT * FROM users;
WHERE status = 'active';
SQL_MARKER

Альтернативы heredoc

Использование printf

Для простых случаев можно использовать printf:

bash
printf "BEGIN;\nUPDATE users SET status = 'active';\nCOMMIT;\n" | psql

Использование here strings

Для однострочного ввода:

bash
psql <<< "BEGIN; UPDATE users SET status = 'active'; COMMIT;"

Использование массивов

Для более сложных сценариев:

bash
sql_commands=(
    "BEGIN;"
    "UPDATE users SET status = 'active';"
    "COMMIT;"
)

printf "%s\n" "${sql_commands[@]}" | psql

Типичные случаи использования

Операции с базами данных

Ваш пример с psql является классическим случаем использования heredoc:

bash
cat << EOF | psql -d myapp
-- Создаем резервную копию
pg_dump -t users > users_backup.sql

-- Очищаем старые данные
TRUNCATE TABLE audit_log;

-- Восстанавливаем из резервной копии
psql myapp < users_backup.sql

-- Создаем отчет
SELECT COUNT(*) FROM users WHERE created_at > NOW() - INTERVAL '7 days';
EOF

Генерация конфигурационных файлов

bash
cat << EOF > /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name myapp.com;
    root /var/www/myapp;
    
    location / {
        try_files \$uri \$uri/ /index.html;
    }
}
EOF

Генерация документации

bash
cat << 'EOF' > README.md
# My Application

This application does amazing things.

## Installation

\`\`\`bash
git clone https://github.com/me/myapp
cd myapp
npm install
\`\`\`
EOF

Документация скриптов

bash
#!/bin/bash
<< 'DOCS'
This script automates database backups.

Usage:
    ./backup.sh [database_name]

Options:
    -h, --help    Show this help message
    -v, --verbose Enable verbose output
DOCS

# Script continues here...

Заключение

Синтаксис cat << EOF - это мощная возможность bash, которая создает here documents (heredoc), позволяя встраивать многострочный текст непосредственно в ваши скрипты. Вот ключевые выводы:

  • Оператор << создает временный поток ввода из встроенного текста
  • Разделитель (по умолчанию EOF) должен стоять в отдельной строке для завершения heredoc
  • Heredoc идеально подходит для SQL-команд, конфигурационных файлов и документации
  • Вы можете контролировать подстановку переменных с помощью кавычек
  • Существуют альтернативы, такие как printf и here strings, для более простых случаев

Для вашего конкретного случая использования с psql, подход с heredoc идеален, так как он позволяет сохранять форматирование SQL и выполнять несколько команд как одну транзакцию. Синтаксис cat << EOF | psql эффективно создает временный SQL-скрипт и передает его напрямую в команду psql.

Для дальнейшего изучения вы можете проверить страницу руководства bash с помощью man bash и найти раздел “REDIRECTIONS”, или поискать “here documents” в документации bash.

Авторы
Проверено модерацией
Модерация