用于管道 heredoc 的多行语法;这是便携式的吗?

Multiline syntax for piping a heredoc; is this portable?

提问人:William Pursell 提问时间:8/13/2011 最后编辑:William Pursell 更新时间:3/21/2019 访问量:52913

问:

我熟悉这个语法:

cmd1 << EOF | cmd2
text
EOF

但刚刚发现 bash 允许我写:

cmd1 << EOF |
text
EOF
cmd2

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

Bash Shell 管道 sh heredoc

评论

0赞 PaulC 12/31/2014
我来这里是为了找到一种将其分成多行的好方法:.“奇怪的语法”似乎是最好的方法。big-long-command1 with lots of args << EOF | big-long-command2 with lots of args
0赞 Sridhar Sarnobat 1/5/2018
一个方便的用例是,当您尝试将空格分隔的表格转换为制表符分隔的表格时,您可以将其粘贴到 Google 电子表格中。您不必创建临时文件。
0赞 Sridhar Sarnobat 1/5/2018
第一个在 z-shell 中对我不起作用。我不喜欢第二个,因为它疏远了 |从命令中,失去 shell 管道的惯用性 (?)。

答:

19赞 Tomas 8/13/2011 #1

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

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

评论

0赞 Sridhar Sarnobat 1/5/2018
还有一个小注意事项:不要在关闭后放置任何空格。提示会表现得很奇怪,你会想知道到底出了什么问题EOF
2赞 Charles Duffy 1/5/2018
在 POSIX 模式下运行 bash 会关闭一些扩展,但绝不会关闭几乎所有扩展。因此,虽然这个答案在POSIX允许的范围内是正确的,但它的推理并不能非常有效地支持这一点。
121赞 Ned Deily 8/13/2011 #2

是的,POSIX标准允许这样做。根据 2008 年版本:

此处文档应被视为一个单词,开头在 下一个并继续,直到有一行只包含 分隔符和 a ,中间没有字符。 然后,如果有,则开始下一个 here-document。<newline><newline><blank>

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

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 */

因此,管道符号后跟行尾,仍可被视为管道的一部分。

28赞 Jens 5/21/2012 #3

是的,它在 POSIX shell 语法中。对于同一命令,您还可以有多个 here-doc(其他一些示例使用两个调用,但这也有效):cat

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

这是人为的(使用 2 个 here-docs 作为 stdin),但如果您考虑为不同的文件描述符提供输入,它会立即变得有意义。

也有可能完全放下。为什么不将 here-document 直接提供给:cmd

cmd << EOF
input
here
EOF

评论

1赞 user1424739 6/1/2015
''' cat <<EOF1 <<EOF2 first here-doc EOF1 second here-doc EOF2 ''' 以上不起作用。
0赞 Jens 6/1/2015
@user1424739 它确实适用于当前的 zsh 和 bash。ash 和 ksh93 似乎只输出第二个 here 文档。
0赞 Jens 1/2/2017
为什么投反对票?如果有不准确的地方,请给我机会进行补救。
0赞 dragon788 7/20/2017
这在使用时非常贴心。sudo tee /etc/securefile.conf <<EOF
3赞 huelbois 7/5/2019
它在什么 bash 版本上工作?使用 bash 4.4.19(在 ubuntu 18.04.02 上)和 bash 5.0(docker 镜像),我只得到了第二个 here-doc。或者也许有一个特定的选择?
9赞 buc 3/21/2019 #4

嗨,例如,检查一下

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

问候