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

Posted

技术标签:

【中文标题】管道化heredoc的多行语法;这是便携式的吗?【英文标题】:Multiline syntax for piping a heredoc; is this portable? 【发布时间】:2011-10-26 03:49:11 【问题描述】:

我熟悉这种语法:

cmd1 << EOF | cmd2
text
EOF

但刚刚发现 bash 允许我写:

cmd1 << EOF |
text
EOF
cmd2

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

【问题讨论】:

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

是的,POSIX 标准允许这样做。 According to the 2008 version:

here-document 应被视为一个单词,开始于 下一个&lt;newline&gt; 并继续直到有一行只包含 分隔符和&lt;newline&gt;,中间没有&lt;blank&gt; 字符。 然后下一个 here-document 开始,如果有的话。

并在同一行中包含多个“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 */

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

【讨论】:

【参考方案2】:

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

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

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

还有可能完全放弃cat。为什么不直接将 here-document 提供给cmd

cmd << EOF
input
here
EOF

【讨论】:

``` cat @user1424739 它在当前的 zsh 和 bash 中工作。 ash 和 ksh93 似乎只输出第二个文档。 为什么投反对票?如果有什么不准确的地方,请给我机会纠正。 这在使用sudo tee /etc/securefile.conf &lt;&lt;EOF 时非常甜蜜。 它在哪个 bash 版本上工作?使用 bash 4.4.19(在 ubuntu 18.04.02 上)和 bash 5.0(docker 映像),我只得到了第二个 here-doc。或者也许有一个特定的选项?【参考方案3】:

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

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

【讨论】:

只是另一个小提示:不要在结束 EOF 之后放置任何空格。提示会表现得很奇怪,你会想知道到底出了什么问题 在 POSIX 模式下运行 bash 会关闭 一些 扩展,但绝不会关闭几乎所有扩展。因此,虽然这个答案在 POSIX 允许的范围内是正确的,但它的推理并不能非常有效地支持这一点。【参考方案4】:

您好,请检查一下,例如

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

问候

【讨论】:

以上是关于管道化heredoc的多行语法;这是便携式的吗?的主要内容,如果未能解决你的问题,请参考以下文章

端口为零的绑定会将您绑定到空闲端口。这是便携的吗? [关闭]

Terraform 会根据运行时环境不断更改多行 heredoc 的行尾

如何使 cat 和 grep 在 c 中的第一个和第二个管道中工作,就像 bash 中的 heredoc <<

PHP 用户PHP的heredoc语法

PHP 语法heredoc

天蓝色管道中的组名称变量可以是动态的吗?