【问题标题】:Why does Bash always add a newline when expanding here strings?为什么 Bash 在此处扩展字符串时总是添加换行符?
【发布时间】:2015-10-20 19:47:30
【问题描述】:

已阅读以下对 Bash 的此功能的描述(摘自手册页):

这里的字符串

here文档的一种变体,格式为:

<<<word

单词被扩展并提供给标准输入上的命令。

我希望这里字符串的解释是 Bash 只是将变量的内容直接传递到命令的标准输入上,未经修改。按照这个逻辑,下面的[1][2] 行实际上是等效的。

[1]~$ printf foo | cat - <(echo end)
fooend
[2]~$ cat - <(echo end) <<<foo
foo
end

但是,Bash 在“扩展”字符串时添加了一个换行符,这是我没有预料到的。即使变量本身以换行符结尾也会发生这种情况:

[3]~$ printf "foo\n" | cat - <(echo end)
foo
end
[4]~$ cat - <(echo end) <<<foo$'\n'
foo

end

在 4.2.25 和 4.3.30 中测试。

所以我的问题是:这种行为是否在 Bash 文档中的任何地方指定?我可以在脚本中依赖它吗?

【问题讨论】:

  • 换行是必需的,文件或流是 UNIX 中的有效文本文件内容。 read 失败(在 has-a-nonzero-exit-status 意义上)没有它们;当输入中的换行符丢失时,多个标准 UNIX 工具的行为未定义。您绝对不会在未来的版本中看到这种变化。
  • @CharlesDuffy 没想到,谢谢。但是,并非每个工具都适用于文本文件(wc -cmd5sum),因此通常命令的标准输入不是必需 是有效的文本文件。此外,Bash 并不总是添加换行符(请参阅帖子中的示例),因此仅此论点并不能解释太多。
  • Chepner 将 herestrings 用作单行 heredocs 的句法糖的历史背景是正确的。
  • ...也就是说,我没有看到问题中的任何示例与我的解释相反。在printf 的情况下,您请求显式控制,这是一个非常独特的情况;在cat 的情况下,bash 无法控制子命令输出的内容,并且也无法看到它——因此它无法查看是否已经有一个尾随换行符来添加缺失的内容一个即使是想要的!
  • @CharlesDuffy 然而,Bash 是扩展 &lt;&lt;&lt;foo$'\n' 的那个,它添加了第二个尾随换行符,而不管字符串已经有一个换行符。您不认为这与您的解释不一致吗?

标签: bash shell newline stdin


【解决方案1】:

不确定,但我相信这里的字符串旨在等同于单行的此处文档,因此

cat <<< foo

cat <<EOF
foo
EOF

是等价的。由于 here 文档总是以换行符结尾,因此 here 字符串也应如此。


考虑一下这里字符串的这个简单用例:

IFS=: read foo bar <<< "a:b"
# foo=a
# bar=b

如果此处的字符串未提供换行符,则 read 的退出状态将为 1。(参见 printf "foo" | { read; echo $?; }printf "foo\n" | { read; echo $?; }。)

【讨论】:

  • 谢谢!这似乎是最合理的解释。
【解决方案2】:

所以我的问题是:这种行为是否在 Bash 文档中的任何地方指定? 我可以在脚本中依赖它吗?

该规范现已添加到Bash Reference Manual

结果以单个字符串的形式提供,并附加一个换行符,以 命令在其标准输入(或文件描述符 n 如果 n 是 指定)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    • 2016-10-10
    • 2020-04-30
    • 2010-11-12
    • 2021-03-22
    • 1970-01-01
    相关资源
    最近更新 更多