Why does Bash always add a newline when expanding

2019-06-01 19:09发布

问题:

Having read the following description of this feature of Bash (excerpt from the man page):

Here Strings

A variant of here documents, the format is:

<<<word

The word is expanded and supplied to the command on its standard input.

I expected that the interpretation of here strings is that Bash simply passes the contents of a variable directly on a command's standard input, unmodified. Following this logic, the lines [1] and [2] below would be effectively equivalent.

[1]~$ printf foo | cat - <(echo end)
fooend
[2]~$ cat - <(echo end) <<<foo
foo
end

However, Bash added a newline when “expanding” a string, something I didn't anticipate. This happens even when a variable ends with newline itself:

[3]~$ printf "foo\n" | cat - <(echo end)
foo
end
[4]~$ cat - <(echo end) <<<foo$'\n'
foo

end

Tested in 4.2.25 and 4.3.30.

So my question is: is this behavior specified anywhere in Bash docs? Can I depend on it in scripts?

回答1:

Not definitive, but I believe a here string is intended to be equivalent to a single-line here document, so that

cat <<< foo

and

cat <<EOF
foo
EOF

are equivalent. Since a here document always ends with a newline, so should the here string.


Consider this simple use case for a here string:

IFS=: read foo bar <<< "a:b"
# foo=a
# bar=b

If a newline weren't provided by the here string, the exit status of read would be 1. (See with printf "foo" | { read; echo $?; } vs printf "foo\n" | { read; echo $?; }.)



回答2:

So my question is: is this behavior specified anywhere in Bash docs? Can I depend on it in scripts?

The specification has now been added to the Bash Reference Manual:

The result is supplied as a single string, with a newline appended, to the command on its standard input (or file descriptor n if n is specified).