basis
HereDoc’s full name is Here Document, or embedded Document in Chinese. There are actually a lot of names for it, here documents, hereis, here-string, and so on.
Embedded documents are an alternative to Shell I/O redirection. We already know that Shell I/O redirection is a transfer of file handles. Such as:
COMMAND 1>/tmp/1.lst 2>&1
Copy the code
The standard output of the command is a file, and the errors are also printed to the same file.
With the case:
cat /etc/passwd | grep '^admin:'
Copy the code
The output of the previous command is piped as the standard input of the later command.
The basic grammar
A Here Document is an alternative to standard input. It enables script developers to produce a file locally and use it as standard input to commands instead of using temporary files to build input information. In general, the format looks like this:
COMMAND <<IDENT
...
IDENT
Copy the code
In this case, << is a bootstrap tag, IDENT is a qualifier selected by the developer, and the content between the two IDENT qualifiers will be treated as a file and used as standard input to COMMAND. For example, to echo a large block of text, we can use the syntax of cat file:
cat <<EOF
SOME TEXT
HERE
!
EOF
Copy the code
In this case, we use the EOF phrase as the qualifier.
A Here Document can be nested, as long as the two layers use different IDENT qualifiers and ensure proper nesting:
ssh user@host <<EOT ls -la --color cat <<EOF from a remote host EOF [ -f /tmp/1.tmp ] && rm -f /tmp/1.tmp EOT Copy the code
Looking a little weird? It’s actually fine.
In fact, qualifiers can be very long, as long as they start with a letter and contain only letters and numbers (in general, underscores and dashes are valid, though they may vary depending on the version of bash and the host implementation).
Here’s an example from ABS, excerpted below:
wall <<zzz23EndOfMessagezzz23
fdjsldj
fdsjlfdsjfdls
zzz23EndOfMessagezzz23
Copy the code
That’s true and valid, but this is actually a little weirder.
Here String
In bash, KSH, and ZSH, you can also use Here String:
$ tr a-z A-Z <<<"Yes it is a string"
YES IT IS A STRING
Copy the code
Variables can also be used:
$ tr a-z A-Z <<<"$var"
Copy the code
Unusual usage
It also redirects standard output
Is it possible to store HEREDOC as a file? Apparently yes:
cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
This line is indented.
EOF
Copy the code
You’ll notice that this is different from regular writing:
cat >/tmp/1<<EOF
s
EOF
Copy the code
But both are right.
root
‘>’ does not work well when root is required, sudo tee is needed:
cat <<EOF | sudo tee /opt/1.log
s
EOF
Copy the code
A subshell
Standard output redirection can also be constructed in the form of a subshell:
(echo '# BEGIN OF FILE | FROM'
cat <<- _EOF_
LogFile /var/log/clamd.log
LogTime yes
DatabaseDirectory /var/lib/clamav
LocalSocket /tmp/clamd.socket
TCPAddr 127.0.0.1
SelfCheck 1020
ScanPDF yes
_EOF_
echo '# END OF FILE'
) > /etc/clamd.conf
Copy the code
This example is just a hint, because it’s actually not that cumbersome, a single Cat HEREDOC will do the trick, and it doesn’t need to be as heavy as opening a subshell.
cat <<EOF
Rare deformation of
let() {
res=$(cat)
}
let <<'EOF'. EOFCopy the code
YuanFang,what’s your opinion?
You can also write like this:
let() {
eval "The $1"'=$(cat)'
}
let res<<'EOF'. EOFCopy the code
Of course, this is the equivalent of a single-line instruction:
{ res=$(cat); } < <'EOF'. EOFCopy the code
{} is a block of statements, not a subshell, so it saves effort. Use it depending on the situation, sometimes you want the variables of the subshell to be pollution-free, or otherwise, use ().
Use HEREDOC in parameter expansion syntax
variable=$(cat <<SETVAR
This variable
runs over multiple lines.
SETVAR
)
echo "$variable"
Copy the code
The example shows how you can embed HEREDOC freely in the $() syntax.
If you just need to assign variables to HEREDOC, read var is usually a better idea:
read i <<!
Hi
!
echo $i # Hi
Copy the code
Use HEREDOC for functions
GetPersonalData () {
read firstname
read lastname
read address
read city
read state
read zipcode
} # This certainly appears to be an interactive function, but . . .
# Supply input to the above function.
GetPersonalData <<RECORD001
Bozo
Bozeman
2726 Nondescript Dr.
Bozeman
MT
21226
RECORD001
echo
echo "$firstname $lastname"
echo "$address"
echo "$city.$state $zipcode"
echo
Copy the code
As you can see, HEREDOC can be applied as long as the function accepts standard input.
Anonymous HEREDOC
#! /bin/bash # filename: aa.sh : <<TESTVARIABLES ${UX? }, ${HOSTNAME? } | ${USER? } | ${MAIL? } # Print error message if one of the variables not set. TESTVARIABLES exit $?Copy the code
In this example, an error message is generated if the variable is not set, and the purpose of this HEREDOC is actually to expand the variable to be validated. HEREDOC produces the result as: The standard input for this variable is actually ignored, and only the HEREDOC expanded status code is returned to verify that a variable has not been set:
$ ./aa; echo $?
./aa: line 3: UX: parameter null or not set
1
Copy the code
Because the UX variable is missing, the result of the call is a line of error output and the call’s exit code is 1, which means false.
: is a synonym for the true command. As if. Were a synonym for the source command.
further
In addition to having the effect of checking whether a large number of variables have been assigned at once, anonymous HEREDOC is also often used for large section comments.
cat >/dev/null<<COMMENT
...
COMMENT
: <<COMMENT
...
COMMENT
Copy the code
You can write any of these, depending on your personal preference. The general style of Bash programmers is to save keyboards when they can. But sometimes they like to show off when they can:
: < < -! ____ _ ____ __ / ___ | ___ ___ __ | | / ___ | ___ ___ __ | | | | _ / _ \ _ \ / _ ` | | | _ / _ \ _ \ / _ ` | | | _ | | | (_) (_ (_) | | | | | _ | | (_) | | (_) (_ | | there comes \ | / ___ / / ___ / \ __, there comes the _ | \ | / ___ / / ___ / \ __, _ | ____ _ _ / ___ | | | _ _ _ __ | | _ _ \ _ \ | __ | | | | / _ ` | | | | ___) | | _ | | _ | | (_ | | | _ | | | ____ / \ | \ (, _ | \ __, _ | \ __, | | ___ /!Copy the code
while read
When we need to read a CSV file, we use the while read structure.
Change the CSV file to HEREDOC:
while read pass port user ip files directs; do
sshpass -p$pass scp -o 'StrictHostKeyChecking no' -P $port $files $user@$ip:$directs
done <<____HERE
PASS PORT USER IP FILES DIRECTS
. . . . . .
. . . . . .
. . . . . .
PASS PORT USER IP FILES DIRECTS
____HERE
Copy the code
Since handling CSV in different formats is not the subject of this article, I won’t go into specifics here.
Added: Loop redirection
For a while… For done, the standard input redirection should be written after done. Likewise, for… The do… C. done D. until The same is true of done.
while
while [ "$name"! = Smith ]# Why is variable $name in quotes?
do
read name # Reads from $Filename, rather than stdin.
echo $name
let "count += 1"
done <"$Filename" # Redirects stdin to file $Filename.
Copy the code
until
until [ "$name" = Smith ] # Change ! = to =.
do
read name # Reads from $Filename, rather than stdin.
echo $name
done <"$Filename" # Redirects stdin to file $Filename.
Copy the code
for
for name in `seq $line_count` # Recall that "seq" prints sequence of numbers.
# while [ "$name" != Smith ] -- more complicated than a "while" loop --
do
read name # Reads from $Filename, rather than stdin.
echo $name
if [ "$name" = Smith ] # Need all this extra baggage here.
then
break
fi
done <"$Filename" # Redirects stdin to file $Filename.
Copy the code
New indentation and alignment syntax
Deletes the TAB indent character
<< -ident is the new syntax, and Bash on the market already supports it. It is special in that all prefix TAB characters in the HEREDOC body content are removed.
This syntax is often used in the if branch of a script, case branch, or other code where indented, so that the HEREDOC closing tag does not have to be at the beginning of a new line. On the one hand, HEREDOC visually follows the indentation level of the code block, improving readability, and on the other hand, for many lazy editors, there is no problem with parsing errors or making incorrect decisions about folded blocks in HEREDOC.
function a () {
if ((DEBUG)); then
cat <<-EOF
French
American
- Uses UTF-8
Helvetica
- Uses RTL
EOF
fi
}
Copy the code
In the script paragraph above, the closing EOF tag does not have to be the first letter of the line, as long as both EOF and the HEREDOC body on it are indented with TAB characters.
Note that the Bash interpreter may report an error if TAB indentation is not strictly observed here.
Like -uses UTF-8 in the text, which contains two Spaces in addition to the TAB indent at the beginning of the line, this is not affected by the <<- deletion.
Disable variable expansion
Normally, statements like ${VAR}, $(PWD), and $((1+1)) in HEREDOC are expanded. When you want to write SSH instructions, you probably want to leave the $tag unexpanded.
This can be done with <<“EOF”.
You only need to surround the IDENT tag with quotation marks to do this; the end tag does not need quotation marks.
cat <<"EOF"
Command is:
$ lookup fantasy
EOF
If you do not want to expand, you need to escape the $character
cat <<EOF
\$ lookup fantasy
EOF
Copy the code
In this example, note that the single $character is actually unexpanded and error-free, so we’re just writing an example.
What about quotation marks, single quotation marks, double quotation marks, they all work the same way.
You can even use escape syntax, that is:
cat <<\EOF
Command is:
$ lookup fantasy
EOF
Copy the code
You can also disable parameter expansion.
Apply both
The two new syntactic features above can be combined and used simultaneously:
cat <<-"EOF"
Command is:
$ lookup fantasy
EOF
Copy the code
Although you probably don’t need to be in this situation.
reference
- Advanced Bash-Scripting Guide – Chapter 19. Here Documents
- Wiki: Here document