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 liked this article, then do subscribe to email alerts for Linux tutorials. If you have any questions or doubts? do ask for help in the comments section.

If You Appreciate What We Do Here On TecMint, You Should Consider:

TecMint is the fastest growing and most trusted community site for any kind of Linux Articles, Guides and Books on the web. Millions of people visit TecMint! to search or browse the thousands of published articles available FREELY to all.

If you like what you are reading, please consider buying us a coffee ( or 2 ) as a token of appreciation.

Support Us

We are thankful for your never ending support.

Got something to say? Join the discussion.

Have a question or suggestion? Please leave a comment to start the discussion. Please keep in mind that all comments are moderated and your email address will NOT be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.