I have noticed several distinction between them:
Inside a <<EOF
heredoc, new values can not be assigned to variables:
bash <<EOF
s=fds
echo $s
EOF
will print empty line, where
bash <<\EOF
s=fds
echo $s
EOF
will print the value of the variable s
.
Global variables can be accessed within <<EOF
but not within <<\EOF
(with export
it is possible to access variables inside <<\EOF
):
s=fds
bash <<EOF
echo $s
EOF
will print the value fds
, where,
s=fds
bash <<\EOF
echo $s
EOF
will print empty line.
So what are the differences between them and what is the legitimate documented behavior?
This operator stands for the end of the file. This means that wherever a compiler or an interpreter encounters this operator, it will receive an indication that the file it was reading has ended. Similarly, in bash, the EOF operator is used to specify the end of the file.
On a serial connection an EOT (End Of Transmission) character indicates a desire to end the transmission. Serial connections are usually accessed using a file driver. When the serial transmission ends, the file driver reports this as an EOF (End Of File) condition. EOF is not a character.
In computing, end-of-file (EOF) is a condition in a computer operating system where no more data can be read from a data source. The data source is usually called a file or stream.
From the POSIX spec:
If any character in word is quoted, the delimiter shall be formed by performing quote removal on word, and the here-document lines shall not be expanded. Otherwise, the delimiter shall be the word itself.
So the <<EOF
version has the shell expand all variables before running the here doc contents and the <<\EOF
(or <<'EOF'
or <<EO'F'
etc.) versions don't expand the contents (which lets bash
in this case do that work).
Try it with cat
instead of bash
for a clearer view on what is happening.
Also with printf '[%s]\n' "$s"
and/or possibly bash -x
instead of bash
:
$ bash -x <<EOF
s=fds
printf '[%s]\n' "$s"
EOF
+ s=fds
+ printf '[%s]\n' ''
[]
$ bash -x <<\EOF
s=fds
printf '[%s]\n' "$s"
EOF
+ s=fds
+ printf '[%s]\n' fds
[fds]
Documentation: http://www.gnu.org/software/bash/manual/bash.html#Here-Documents
In your first example the delimiter is unquoted, so variable expansion occurs and it's like you're running the code
echo "s=fds
echo $s" | bash
which expands $s
in the current shell, where it's empty. So the new shell sees
s=fds
echo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With