Hi,
On 07/06/2023 14:26, наб wrote:
Forwarding from Debian #1037195:
bullseye (0.5.11+git20200708+dd9ef66-5),
sid (0.5.12-2) and
git (b00288fd28c1b39d0f1531b6e6d86de59de4be8d)
dash observe the following:
$ cat -n boment
1 echo "$(head -n1 <<EOF)"
2 # 2
3 # 3
4 EOF
$ sh boment
boment: 4: EOF: not found
$ sh -x boment
+ head -n1
+ echo
+ EOF
boment: 4: EOF: not found
$
This agrees with bullseye bash (5.1-2+deb11u1) but not sid bash
(5.2.15-2+b2), which outputs "# 2" (and a warning);
I believe that bash is correct here (sans the warning).
As far as I know, this is not intended to be valid. Shells are permitted
but not required to accept it, and if they accept it, it need not behave
in any particular way.
POSIX Issue 7, XCU, 2. Shell Command Language says
2.7.4 Here-Document
The redirection operators "<<" and "<<-" both allow redirection of subsequent lines read by the shell to the input of a command. The redirected lines are known as a "here-document".
The here-document shall be treated as a single word that begins after the next <newline> and continues until there is a line containing only the delimiter and a <newline>, with no <blank> characters in between. Then the next here-document starts, if there is one. The format is as follows:
and its counterpart in Issue 8 Draft 3
80601 2.7.4 Here-Document
80602 The redirection operators "<<" and "<<-" both allow redirection of subsequent lines read by
80603 the shell to the input of a command. The redirected lines are known as a ``here-document’’.
80604 The here-document shall be treated as a single word that begins after the next NEWLINE token
80605 and continues until there is a line containing only the delimiter and a <newline>, with no
80606 <blank> characters in between. Then the next here-document starts, if there is one. For the
80607 purposes of locating this terminating line, the end of a command_string operand (see sh) shall be
80608 treated as a <newline> character, and the end of the commands string in $(commands) and
80609 `commands` may be treated as a <newline>. If the end of input is reached without finding the
80610 terminating line, the shell should, but need not, treat this as a redirection error. The format is as
80611 follows:
The relevant bit here is "If the end of input is reached without finding
the terminating line, the shell should, but need not, treat this as a
redirection error."
The command substitution's command is head -n1 <<EOF. There is no
terminator for the <<EOF heredoc in the command substitution's command.
There is not even the newline to start the heredoc. Issue 8 says this
should be (but needn't be) treated as a redirection error. If a shell
does not treat it as a redirection error, the behaviour is implicitly
unspecified.
Even in Issue 7, it says "continues until there is a line containing
only the delimiter and a <newline>", with nothing to say what happens
when no such line is found, also implicitly making the behaviour
unspecified.
That said, this did use to work in dash as it does in bash, and both
this and the otherwise equivalent form with `` (which never worked in
bash or dash, as far as I know) are possible to support if dash so
desires: I have implemented this in my own version a while ago. It
works. It is possible for dash to do the same.
Cheers,
Harald van Dijk