How to Use Heredoc in Shell Scripting

Here document (Heredoc) is an input or file stream literal that is treated as a special block of code. This block of code will be passed to a command for processing. Heredoc originates in UNIX shells and can be found in popular Linux shells like sh, tcsh, ksh, bash, zsh, csh. Notably, other programming languages like Perl, Ruby, PHP also support heredoc.

Structure of Herdoc

Heredoc uses 2 angle brackets (<<) followed by a delimiter token. The same delimiter token will be used to terminate the block of code. Whatever comes within the delimiter is considered to be a block of code.

Look at the example below. I am redirecting the block of code to the cat command. Here the delimiter is set to “BLOCK” and terminated by the same “BLOCK“.

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

NOTE: You should use the same delimiter token to start the block and terminate the block.

Create Multiline Comments

If you are coding sometime in bash now, you may know bash by default doesn’t support multiline comments like C or Java. You can use HereDoc to overcome this.

This is not a built-in feature of bash supporting multi-line comment, but just a hack. If you are not redirecting heredoc to any command, the interpreter will simply read the block of code and will not execute anything.

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

Handling White Spaces

By default, heredoc will not suppress any white space characters (tabs, spaces). We can override this behavior by adding dash (-) after (<<) followed by a delimiter. This will suppress all tab spaces but white spaces will not be suppressed.

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
Handling Spaces
Handling Spaces

Variable and Command Substiution

Heredoc accepts variable substitution. Variables can be user-defined variables or environmental variables.

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

Similarly, you can run any commands inside the heredoc code block.

cat << BLOCK2
$(uname -a) 
BLOCK2
Variable and Command Substitution
Variable and Command Substitution

Escaping Special Characters

There are several ways we can escape special characters. Either you can do it at the character level or doc level.

To escape individual special characters use a backslash (\).

cat << BLOCK4
$(uname -a)
BLOCK4

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

To escape all the special characters inside the block surround the delimiter with single quotes, double quotes, or prefix delimiter with a backslash.

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

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

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

Now that we know the structure of heredoc and how it works, let’s see a few examples. Two common areas where I use heredoc are running a block of commands over SSH and passing SQL queries through heredoc.

In the below example, we are trying to execute a block of code in a remote server through SSH.

Running Commands Over SSH
Running Commands Over SSH

In the below example I am passing a select statement to psql to connect to a database and run the query. This is an alternative way to run a query in psql inside bash script instead of using the -f flag to run .sql file.

#!/usr/bin/env bash

UNAME=postgres
DBNAME=testing

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

That’s it for this article. There is a lot more you can do with heredoc compared to what we have shown in the examples. If you have any useful hack with heredoc please post it in the comment section so our readers could benefit from that.

If you read this far, tweet to the author to show them you care. Tweet a thanks
Karthick Sudhakar
I am a Big data Engineer from India, Chennai working on a top MNC with a vision of being a bridge between technology and mankind.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

Got something to say? Join the discussion.

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.