Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links.
Alternatively you can here view or download the uninterpreted raw source code.
A member file download can also be achieved by clicking within a package contents listing on the according byte size field.

Chapter 19. Here Documents

A here document is a special-purpose
code block. It uses a form of I/O
redirection to feed a command list to
an interactive program or a command, such as ftp, cat,
or the ex text editor.

COMMAND <<InputComesFromHERE
...
...
...
InputComesFromHERE

A limit string delineates (frames)
the command list. The special symbol << precedes
the limit string. This has the effect of redirecting the output
of a command block into the stdin of the program
or command. It is similar to interactive-program <
command-file, where command-file
contains

Even such unlikely candidates as the vi
text editor lend themselves to here
documents.

Example 19-2. dummyfile: Creates a 2-line dummy
file

#!/bin/bash
# Noninteractive use of 'vi' to edit a file.
# Emulates 'sed'.
E_BADARGS=85
if [ -z "$1" ]
then
echo "Usage: `basename $0` filename"
exit $E_BADARGS
fi
TARGETFILE=$1
# Insert 2 lines in file, then save.
#--------Begin here document-----------#
vi $TARGETFILE <<x23LimitStringx23
i
This is line 1 of the example file.
This is line 2 of the example file.
^[
ZZ
x23LimitStringx23
#----------End here document-----------#
# Note that ^[ above is a literal escape
#+ typed by Control-V <Esc>.
# Bram Moolenaar points out that this may not work with 'vim'
#+ because of possible problems with terminal interaction.
exit

The above script could just as effectively have been implemented with
ex, rather than
vi. Here
documents containing a list of ex
commands are common enough to form their own category, known as
ex scripts.

#!/bin/bash
# 'echo' is fine for printing single line messages,
#+ but somewhat problematic for for message blocks.
# A 'cat' here document overcomes this limitation.
cat <<End-of-message
-------------------------------------
This is line 1 of the message.
This is line 2 of the message.
This is line 3 of the message.
This is line 4 of the message.
This is the last line of the message.
-------------------------------------
End-of-message
# Replacing line 7, above, with
#+ cat > $Newfile <<End-of-message
#+ ^^^^^^^^^^
#+ writes the output to the file $Newfile, rather than to stdout.
exit 0
#--------------------------------------------
# Code below disabled, due to "exit 0" above.
# S.C. points out that the following also works.
echo "-------------------------------------
This is line 1 of the message.
This is line 2 of the message.
This is line 3 of the message.
This is line 4 of the message.
This is the last line of the message.
-------------------------------------"
# However, text may not include double quotes unless they are escaped.

The - option to mark a here document limit string
(<<-LimitString) suppresses leading
tabs (but not spaces) in the output. This may be useful in making
a script more readable.

Example 19-4. Multi-line message, with tabs suppressed

#!/bin/bash
# Same as previous example, but...
# The - option to a here document <<-
#+ suppresses leading tabs in the body of the document,
#+ but *not* spaces.
cat <<-ENDOFMESSAGE
This is line 1 of the message.
This is line 2 of the message.
This is line 3 of the message.
This is line 4 of the message.
This is the last line of the message.
ENDOFMESSAGE
# The output of the script will be flush left.
# Leading tab in each line will not show.
# Above 5 lines of "message" prefaced by a tab, not spaces.
# Spaces not affected by <<- .
# Note that this option has no effect on *embedded* tabs.
exit 0

A here document supports parameter and
command substitution. It is therefore possible to pass different
parameters to the body of the here document, changing its output
accordingly.

Example 19-5. Here document with replaceable parameters

#!/bin/bash
# Another 'cat' here document, using parameter substitution.
# Try it with no command-line parameters, ./scriptname
# Try it with one command-line parameter, ./scriptname Mortimer
# Try it with one two-word quoted command-line parameter,
# ./scriptname "Mortimer Jones"
CMDLINEPARAM=1 # Expect at least command-line parameter.
if [ $# -ge $CMDLINEPARAM ]
then
NAME=$1 # If more than one command-line param,
#+ then just take the first.
else
NAME="John Doe" # Default, if no command-line parameter.
fi
RESPONDENT="the author of this fine script"
cat <<Endofmessage
Hello, there, $NAME.
Greetings to you, $NAME, from $RESPONDENT.
# This comment shows up in the output (why?).
Endofmessage
# Note that the blank lines show up in the output.
# So does the comment.
exit

This is a useful script containing a here
document with parameter substitution.

Quoting or escaping the "limit string" at the
head of a here document disables parameter substitution within its
body. The reason for this is that quoting/escaping the
limit string effectively escapes the $,
`, and \special characters, and causes them to
be interpreted literally. (Thank you, Allen Halsey, for pointing
this out.)

Example 19-7. Parameter substitution turned off

#!/bin/bash
# A 'cat' here-document, but with parameter substitution disabled.
NAME="John Doe"
RESPONDENT="the author of this fine script"
cat <<'Endofmessage'
Hello, there, $NAME.
Greetings to you, $NAME, from $RESPONDENT.
Endofmessage
# No parameter substitution when the "limit string" is quoted or escaped.
# Either of the following at the head of the here document would have
#+ the same effect.
# cat <<"Endofmessage"
# cat <<\Endofmessage
# And, likewise:
cat <<"SpecialCharTest"
Directory listing would follow
if limit string were not quoted.
`ls -l`
Arithmetic expansion would take place
if limit string were not quoted.
$((5 + 3))
A a single backslash would echo
if limit string were not quoted.
\\
SpecialCharTest
exit

Disabling parameter substitution permits outputting literal text.
Generating scripts or even program code is one use for this.

A variation of the above technique permits "commenting
out" blocks of code.

Example 19-11. Commenting out a block of code

#!/bin/bash
# commentblock.sh
: <<COMMENTBLOCK
echo "This line will not echo."
This is a comment line missing the "#" prefix.
This is another comment line missing the "#" prefix.
&*@!!++=
The above line will cause no error message,
because the Bash interpreter will ignore it.
COMMENTBLOCK
echo "Exit value of above \"COMMENTBLOCK\" is $?." # 0
# No error shown.
echo
# The above technique also comes in useful for commenting out
#+ a block of working code for debugging purposes.
# This saves having to put a "#" at the beginning of each line,
#+ then having to go back and delete each "#" later.
# Note that the use of of colon, above, is optional.
echo "Just before commented-out code block."
# The lines of code between the double-dashed lines will not execute.
# ===================================================================
: <<DEBUGXXX
for file in *
do
cat "$file"
done
DEBUGXXX
# ===================================================================
echo "Just after commented-out code block."
exit 0
######################################################################
# Note, however, that if a bracketed variable is contained within
#+ the commented-out code block,
#+ then this could cause problems.
# for example:
#/!/bin/bash
: <<COMMENTBLOCK
echo "This line will not echo."
&*@!!++=
${foo_bar_bazz?}
$(rm -rf /tmp/foobar/)
$(touch my_build_directory/cups/Makefile)
COMMENTBLOCK
$ sh commented-bad.sh
commented-bad.sh: line 3: foo_bar_bazz: parameter null or not set
# The remedy for this is to strong-quote the 'COMMENTBLOCK' in line 49, above.
: <<'COMMENTBLOCK'
# Thank you, Kurt Pfeifle, for pointing this out.

The closing limit string,
on the final line of a here document, must start in the
first character position. There can
be no leading whitespace. Trailing
whitespace after the limit string likewise causes unexpected
behavior. The whitespace prevents the limit string from being
recognized.
[1]

#!/bin/bash
echo "----------------------------------------------------------------------"
cat <<LimitString
echo "This is line 1 of the message inside the here document."
echo "This is line 2 of the message inside the here document."
echo "This is the final line of the message inside the here document."
LimitString
#^^^^Indented limit string. Error! This script will not behave as expected.
echo "----------------------------------------------------------------------"
# These comments are outside the 'here document',
#+ and should not echo.
echo "Outside the here document."
exit 0
echo "This line had better not echo." # Follows an 'exit' command.

Some people very cleverly use a
single ! as a limit string. But, that's not
necessarily a good idea.

# This works.
cat <<!
Hello!
! Three more exclamations !!!
!
# But . . .
cat <<!
Hello!
Single exclamation point follows!
!
!
# Crashes with an error message.
# However, the following will work.
cat <<EOF
Hello!
Single exclamation point follows!
!
EOF
# It's safer to use a multi-character limit string.

For those tasks too complex for a here
document, consider using the
expect scripting language, which
was specifically designed for feeding input into interactive
programs.