Bash Heredoc – Understanding Strange Behavior of Nested Heredoc

bashhere-document

Sorry if dup. I couldn't find any similar issue here, though.
I accidentally found this strange behavior. Could anyone explain this logic?
Why parsed as 'ABC'?

$ cat repro.sh
bash -s <<-EOS1
        bash -s <<EOS2 &
        #ABC
        EOS2
echo "" | wc
#1234567
EOS1

$ . ./repro.sh
      1       0       1
bash: line 5: ABC: command not found
bash: line 6: EOS2: command not found
      1       0       1

Best Answer

This is a bug in bash. You should submit a bug report at bug-bash@gnu.org.

A more spectacular example -- as you can see, it's the combination of "script from stdin", "stdin as a seekable file" and "heredoc from background command" which triggers it, nesting heredocs is not sufficient or necessary:

$ cat a.sh
true <<EOF &
#ABC
EOF
seq 1 3
true | true
#1234567
$ bash <a.sh
1
2
3
bash: line 5: rue: command not found
1
2
3
bash: line 9: rue: command not found
1
...
<same nonsense repeated hundred of times with increasing line numbers>

You can bypass it with a "useless" use of cat on the outer bash (tabs omitted from your example since this site mangles them):

cat <<-EOS1 | bash -s

bash -s <<EOS2 &
#ABC
EOS2

echo "" | wc
#1234567
EOS1

Since the script will be read from a pipe, this will convince bash to read it byte-by-byte (a system call for each byte) instead of trying to cut corners by seeking back and forth into the input ;-)

Related Question