为什么bash此处字符串会添加尾随换行符?


34

以下示例显示了将新行添加到here-string的情况
为什么要这样做?

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

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

Answers:


38

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

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

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

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

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


比我的回答要彻底得多。
麦克

2
Bash可能是从ksh93借来了这里的字符串,但ksh又从zsh借来了它们,后者是从Plan 9 shell rc中获取的
Mark Reed

2
<<<被引进到了伯恩世界zsh,而不是ksh。它是由在Unix端口类似的运营商的启发rc这并没有增加额外的换行符。有趣的是,=(<<<text)运算符没有在中添加该换行符zsh
斯特凡Chazelas

如果您想知道对此答案的兴趣是因为SO中存在这个问题
fedorqui

1
有什么办法可以写here-string(无需使用其他工具,如printf等等),避免在其中拖尾换行符bash?就像@StéphaneChazelas一样,指向中也可能zsh
CTodea

3

readset -emode处于活动状态时使用命令时,将换行符附加到here-string的一种实际情况是。回忆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'

-3

我认为这是在here字符串末尾证明换行的唯一方法:

xxd <<<`echo -ne "a\n"`

除非您提交的语法中给出了换行符,否则here-string运算符似乎会删除换行符。


4
这是删除最后换行符的命令替换。您可以将其简化为xxd <<<$(echo a)
吉尔斯(Gilles)“所以,别再邪恶了”,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.