4. Here documents
A here document is an additional form of I/O redirection in which we embed a body of text into our script and feed it into the standard input of a command. It works like this:
command << token
. . . . .
text
. . . . .
token
where command is a command that accepts standard input and token is a string used to indicate the end of the embedded text. It should be at the beginning of the line and should have no trailing spaces.
-
Let's modify the script to use a here document:
vim sys_info.sh
/echo
Press capital
O
and type:cat << _EOF_
Press ESC and then
G
ando
to go to the end of the buffer and open a new line. Then type:_EOF_
Press ESC and give this substitute command:
:%s/echo "//
Gk$x
:wq
The script now should look like this:
#!/bin/bash
# Program to output a system information page.
declare -r TITLE="System Information Report for $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIMESTAMP="Generated on $CURRENT_TIME, by $USER"
cat << _EOF_
<html>
<head>
<title>$TITLE</title>
</head>
<body>
<h1>$TITLE</h1>
<p>$TIMESTAMP</p>
</body>
</html>
_EOF_./sys_info.sh
Instead of using
echo
, the script now usescat
and a here document. -
The advantage of a here document is that inside the text we can freely use single and double quotes, since they are not interpreted by the shell as delimiters of a string. For example:
foo="some text"
cat << EOF
$foo
"$foo"
'$foo'
\$foo
EOFThe shell treats the quotation marks as ordinary characters.
-
We also notice that the variables inside the text are expanded. To prevent variable expansion we can enclose the token in quotes:
cat << "EOF"
$foo
"$foo"
'$foo'
\$foo
EOFcat << 'EOF'
$foo
"$foo"
'$foo'
\$foo
EOF -
Here documents can be used with any command that accepts standard input. For example we can use it with
ftp
to retrieve a file:ftp1.sh
#!/bin/bash
# Script to retrive a file via FTP
FTP_SERVER=ftp.nl.debian.org
FTP_PATH=/debian/dists/bookworm/main/installer-amd64/current/images/cdrom/
REMOTE_FILE=debian-cd_info.tar.gz
ftp -n << _EOF_
open $FTP_SERVER
user anonymous me@linuxbox
cd $FTP_PATH
get $REMOTE_FILE
bye
_EOF_
ls -l $REMOTE_FILEvim ftp1.sh
:q!
./ftp1.sh
If we change the redirection operator from
<<
to<<-
, the shell will ignore the leading tab characters in the here document. This allows a here document to be indented, which can improve readability.ftp2.sh
#!/bin/bash
# Script to retrive a file via FTP
FTP_SERVER=ftp.nl.debian.org
FTP_PATH=/debian/dists/bookworm/main/installer-amd64/current/images/cdrom/
REMOTE_FILE=debian-cd_info.tar.gz
ftp -n <<- _EOF_
open $FTP_SERVER
user anonymous me@linuxbox
cd $FTP_PATH
get $REMOTE_FILE
bye
_EOF_
ls -l $REMOTE_FILEvim ftp2.sh
:q!
./ftp2.sh