为什么 shell 命令替换会吞下尾随的换行符?

Pet*_*r.O 27 shell text-processing command-substitution

根据以下示例,以及我最近的问题 在 bash 中,尾随的换行符去哪儿了?,我想知道它“为什么”发生

  x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p 
# Output is: 610a62 
# The trailing newline from the 'echo' command
#   has been "deleted" by Command Substitution
Run Code Online (Sandbox Code Playgroud)

我认为shell 操作必须有一些非常重要的原因,即命令替换,从它正在替换的命令输出中实际删除一些数据......
但我无法理解这个,因为它似乎是它该做什么的对立面......即。将命令的输出传递回脚本进程......保留一个字符对我来说似乎很奇怪,但我认为有一个合理的原因......我很想知道这个原因是什么...... .

Sté*_*nez 22

因为 shell 最初并不打算成为一种完整的编程语言。

\n从某些命令输出中删除尾随非常困难。但是,出于显示目的,几乎所有命令都以 结束其输出\n,因此……当您想在另一个命令中使用它时,必须有一种简单的方法将其删除。$()选择的解决方案是通过结构自动移除。

所以,也许你会接受这个问题作为答案:

\n如果以下命令没有自动完成,您能找到一种简单的方法来删除尾随吗?

> echo The current date is "$(date)", have a good day!
Run Code Online (Sandbox Code Playgroud)

请注意,需要引用以防止可能出现在格式化日期中的双空格被粉碎。

  • 如果你说的是真的,那我绝对会惊呆了。如果有一个 `shopt` 来改变你所描述的默认行为,那么我会再次高兴......我发现很难认为 Bash/Linux/Unix 会仅仅因为 ` date` 没有带/不带 '\n' 选项...明显的解决办法是 bash(或其他 shell)为此有一个 `shopt`...你知道吗?..您是否有任何参考链接来说明此问题的原因和原因?...为什么 `date` 没有 \n 选项..它应该! (2认同)
  • 命令替换出现在 1979 年 Unix 的“第 7 版”中的 [Bourne shell 的第一个版本](http://www.in-ulm.de/~mascheck/bourne/#version7) 中。它已经是一个 *大* 革命,我猜(我不是天生的)没有人关心是否保持尾随 '\n' 。是的,您可以在不到 10 分钟的时间内阅读 [手册页](http://www.in-ulm.de/~mascheck/bourne/v7/),在此之前,命令替换似乎没有任何改变。除了首选的“$()”替代语法。 (2认同)

Ste*_*ard 19

这是标准的一部分:

shell 应通过在子 shell 环境中执行命令来扩展命令替换(请参阅Shell 执行环境)并将命令替换(命令文本加上封闭的“$()”或反引号)替换为命令的标准输出,删除替换结束时的一个或多个 <newline> 的序列。

当然,标准可能是这样写的,因为它是怎么ksh做的,但它是标准,它是记录在案的行为。如果您不喜欢它,请使用 Perl 或其他可以让您保留尾随换行符的东西。

  • 标准就是这样,因为这就是 Bourne shell 和此后所有其他 shell 的方式。 (4认同)

Eig*_*ony 6

嗯,这对我来说很有意义。换行符仅出现在正常命令输出中的第一位,以便在命令完成后在新行上出现提示。在大多数情况下,换行符不是原始输出的一部分,它用于整理屏幕。当您解析命令的输出时,末尾的换行符通常很麻烦。为什么wc命令输出2行文本?哦,它没有,它输出一个后跟一个换行符。当您解析时,wc您不想担心有 2 行输出这一事实——实际上并没有,只有一行。