用于管道传输 herdoc 的多行语法; 这是可移植的吗?

我对这个句法很熟悉:

cmd1 << EOF | cmd2
text
EOF

但是刚刚发现 bash 允许我写:

cmd1 << EOF |
text
EOF
cmd2

(heredoc 用作 cmd1的输入,cmd1的输出通过管道传输到 cmd2)。这似乎是一个非常奇怪的语法。便携式的吗?

48612 次浏览

嗯,我想是的,根据在 POSIX 模式下的 bash 测试:

$ bash --posix
$ cat <<EOF |
> ahoj
> nazdar
> EOF
> sed 's/a/b/'
bhoj
nbzdar

是的,POSIX 标准允许这样做

这里的文件应被视为一个单一的字,开始后 下一个 <newline>,并继续,直到有一行只包含 分隔符和 <newline>,中间没有 <blank>字符。 然后这里的下一个文档开始,如果有的话。

并在同一行中包含多个“ here-document”的示例:

cat <<eof1; cat <<eof2
Hi,
eof1
Helene.
eof2

所以做重定向或管道没有问题,你的例子类似于这样的东西:

cat file |
cmd

Shell 语法(在链接页面的下面)包括以下定义:

pipe_sequence    :                             command
| pipe_sequence '|' linebreak command


newline_list     :              NEWLINE
| newline_list NEWLINE
;
linebreak        : newline_list
| /* empty */

因此,管道符号后面可以跟一个行结束符,并且仍然被认为是管道的一部分。

是的,它在 POSIX shell 语法中。您还可以使用 这里不止一个-博士为同一命令(其他一些示例使用两个 cat调用,但这也可以工作) :

cat <<EOF1 <<EOF2
first here-doc
EOF1
second here-doc
EOF2

这是人为设计的(对 stdin 使用2 here-docs) ,但是如果您考虑为不同的文件描述符提供输入,那么它立即就有意义了。

完全放弃 cat也有这种可能性。为什么不把 here-document 直接提供给 cmd:

cmd << EOF
input
here
EOF

比如说,看看这个

#!/bin/sh
( base32 -d | base64 -d )<<ENDOFTEXT
KNDWW42DNNSHS5ZXPJCG4MSVM5MVQVT2JFCTK3DELBFDCY2IIJYGE2JUJNHWS22LINVHQMCMNVFD
CWJQIIZVUV2JOVNEOVJLINTW6PIK
ENDOFTEXT

问候