Bash Heredoc

When writing shell scripts, you may need to pass a multi-line block of text or code to an interactive command such as tee, cat, or sftp.

Bash Heredoc

In Bash and other shells (e.g., Zsh), a here-document (heredoc) is a form of redirection that allows you to pass multiple lines of input to a command.

[COMMAND] <<[-] DELIMITER
  HERE-DOCUMENT
DELIMITER
  • The first line starts with an optional command, the operator <<, and a delimiter identifier.

    • Any string can be a delimiter; EOF or END are often used.
    • If the delimiter is not quoted (' or "), variable substitution, command substitution, etc., are performed.
    • Using <<- causes the shell to remove leading tabs from the here-document (spaces are not removed).
  • The last line must contain only the delimiter (with no leading spaces or characters at the end).

Examples of heredoc

Output with variables

Heredoc is most commonly used with cat.

cat << EOF
Current working directory: $PWD
You are logged in as: $(whoami)
EOF

We get:

Current working directory: /home/linuxize
You are logged in as: linuxize

Without variable substitution

Quoting the delimiter disables substitution:

cat << "EOF"
Current working directory: $PWD
You are logged in as: $(whoami)
EOF

We get:

Current working directory: $PWD
You are logged in as: $(whoami)

With indentation in condition

You can use the redirection operation <<-, which allows you to set left indentation in the code.

This can be useful when the heredoc is inside a statement or loop where it would be nice to add a left indent to the code:

if true; then
	cat <<- EOF
	A line with leading tab.
	EOF
fi

Assigning to a variable

A simple example:

COMMAND=$(cat << BASH
your command here
BASH
)

Another example using variables:

DB_USER=db_user
DB_NAME=db_name
DB_PASSWORD=db_pass

COMMAND=$(cat << BASH
mysql -u "$DB_USER" -p"$DB_PASSWORD" -e "USE $DB_NAME;" 2>/dev/null
if ! \$?; then
	mysql -u "$DB_USER" -p"$DB_PASSWORD" -e "CREATE DATABASE $DB_NAME;"
fi
BASH
)

echo "$COMMAND"

We get:

mysql -u "db_user" -p"db_pass" -e "USE db_name;" 2>/dev/null
if ! $?; then
	mysql -u "db_user" -p"db_pass" -e "CREATE DATABASE db_name;"
fi

Writing to a file

Instead of outputting to the screen, you can redirect it to a file using the operators >, >>. If the file file.txt does not exist, it will be created. When using >, the file will be overwritten, while >> will append the output to the end of the file:

cat << EOF > file.txt
Current working directory: $PWD
You are logged in as: $(whoami)
EOF

Pipe to sed or write to file

Heredoc input can also be piped (|). In the following example, the sed command will replace all occurrences of the character l with e:

cat <<'EOF' | sed 's/l/e/g'
Hello
World
EOF

We get:

Heeeo
Wored

Writing data from the pipeline to a file:

cat <<'EOF' | sed 's/l/e/g' > file.txt
Hello
World
EOF

Using heredoc with SSH

Using heredoc is one of the most convenient and straightforward ways to execute multiple commands on a remote system via SSH.

When using an unquoted delimiter, ensure that you escape all variables, commands, and special characters; otherwise, they will be interpolated locally:

ssh -T [email protected] << EOF
echo "Local working directory: $PWD"
echo "Remote working directory: \$PWD"
EOF

We get:

Local working directory: /home/linuxize
Remote working directory: /home/user

Conclusion

Heredoc, here-document, многострочный ввод Bash, перенаправление «<<EOF», оператор «<<-», вставка блоков текста, скрипт Linux, shell-скриптинг, автоматизация команд, cat tee ssh sed, вывод в файл, переменные в here-doc, удаление табов, примеры heredoc в bash-скриптах, передача кода, командная строка Linux, scripting tips, bash heredoc examples, EOF delimiter, многострочная строка в shell, вывод без интерполяции, <<'EOF', pipe в sed, SSH remote commands, удобная вставка текста, Linux CLI.

--

Source: https://linuxize.com/post/bash-heredoc/