为什么 bash here-string 添加尾随换行符?

Pet*_*r.O 43 bash text-processing

以下示例显示向here-string添加了一个换行符。
为什么要这样做?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 45

简单的答案是因为 ksh 是这样编写的(并且 bash 是兼容的)。但这种设计选择是有原因的。

大多数命令都需要文本输入。在 unix 世界中,文本文件由一系列行组成,每行都以换行符结尾。所以在大多数情况下需要最后的换行符。一个特别常见的情况是使用命令替换获取命令的输出,以某种方式处理它,然后将其传递给另一个命令。命令替换删除最后的换行符;<<<放一个回来。

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp
Run Code Online (Sandbox Code Playgroud)

Bash 和 ksh 无论如何都不能操作二进制数据(它不能处理空字符),因此它们的功能面向文本数据也就不足为奇了。

<<<下面的字符串语法大多只是为了方便反正,就像<<这里的文档。如果您不需要添加最后的换行符,请使用echo -n(在 bash 中)或printf和管道。

  • Bash 可能从 ksh93 借用了 here-strings,但 ksh 反过来又从 zsh 借用了它们,zsh 从 Plan 9 shell *rc* 中获得了它们。 (2认同)
  • `&lt;&lt;&lt;` 是由 `zsh` 而非 `ksh` 引入 Bourne 世界的。它的灵感来自于 `rc` 的 Unix 端口中的一个类似操作符,它_不_添加那个额外的换行符。有趣的是,`=(&lt;&lt;&lt;text)` 运算符不会在 `zsh` 中添加该换行符。 (2认同)

Dej*_*ton 5

将换行符附加到 here-strings 的一种实际情况是readset -emode 处于活动状态时使用该命令。回想一下,set -e当脚本(或多或少)遇到生成非零状态代码的语句时,它会导致脚本终止。考虑read在遇到没有换行符的字符串时生成非零状态代码:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'
Run Code Online (Sandbox Code Playgroud)