In some cases, you may have a long multi-line string for input to a command in your script that you don't want to separate into another file. This is often the case with output for -h or --help options, where you don't want to store the help information outside the script.
Because quoted strings can include multiple lines, we can just use printf for this; it works fine, emitting multiple lines of output:
#!/bin/bash
case $1 in
-h|--help)
printf '%s\n' 'foo command help:
-h, --help: Show this help
-q, --quiet: Run without diagnostics
-v, --verbose: Add extra diagnostics'
exit 0
;;
esac
For commands that accept the data as input, such as cat, rather than in argument, such as printf, a different syntax can be used: a here-document, a kind of quoting that uses a token word or delimiter to specify where a document for a command's standard input should finish.
The preceding snippet could be rewritten to use a here-document in cat, instead of an argument to printf:
#!/bin/bash
case $1 in
-h|--help)
cat <<'EOF'
foo command help:
-h, --help: Show this help
-q, --quiet: Run without diagnostics
-v, --verbose: Add extra diagnostics
EOF
exit 0
;;
esac
This includes as input to cat all lines that are between the <<'EOF' line and the next occurrence of the EOF token as the first word of a new line; in this case, this is a total of four lines of data, each terminated with a newline character. That data becomes the standard input to cat, which in turn prints it to the program's standard output.
Note the following details of this syntax:
- The redirection operator is two left angled brackets, <<. Having only one left angled bracket will trigger plain old file-input redirection – not what you intended!
- The lines in the data are not indented at the same level as the rest of the case structure. This is because the leading whitespace will be interpreted literally, and printed exactly as you write it. We say that leading whitespace is not stripped.
- Similarly, the terminating delimiter that flags the end of the here-document is the only content on the line, with no leading whitespace. If you include whitespace before the delimiter, the line is taken as part of the input.
- The token word, the delimiter, is EOF. This is only a common convention; it can be any string (if quoted).
- The delimiter is in single quotes. Similar to the behavior of single quotes, this specifies that until the EOF is reached, all of the characters in the data should be treated literally, including $.
If you want to expand variables or do command substitution inside a here-document, you can leave out the single quotes around the delimiter. The here-document then expands variables and substitutions inside it, much like a double-quoted string. This allows you to use values from the environment or elsewhere in the program in the string:
#!/bin/bash cat <<EOF Hello, $USER; you are running this program on $(hostname -s). Your home directory is $HOME. EOF
If you really want to indent your here-documents, there is an exception to the preceding rule about leading whitespace; if you include a hyphen between << and the delimiter, the tabs (but not spaces) at the front of your input lines will be ignored:
#!/bin/bash
cat <<-'EOF'
Leading tabs
will not be included in the output
EOF