为什么 bash 删除 $(cat 文件) 中的 \n?

f.a*_*ian 32 command-line bash

如果我的文件input.txt包含:

hello
world
!
Run Code Online (Sandbox Code Playgroud)

然后执行 bash 命令echo $(cat input.txt)会输出这个:

hello world !
Run Code Online (Sandbox Code Playgroud)

为什么以及如何修复它以准确输出文件中的内容?

ari*_*ian 42

如果你使用

echo "$(cat input.txt)"
Run Code Online (Sandbox Code Playgroud)

它会正常工作。

可能echo 的输入是用换行符分隔的,它会作为单独的命令处理,所以结果将没有换行符。

  • @KeithThompson 是的,命令替换会从输出中删除所有尾随换行符。这有一个优点,例如`echo "$(date) something"` 从日期的输出中去除尾随的换行符,使该回显在同一行上输出日期和“某物”。如果您需要“按原样”存储文件或命令输出,请使用 mapfile (`help mapfile`)、`read -rd ''` 或 while read-loop。 (6认同)
  • 但是 *final* 换行符被省略,即使在双引号中也是如此。相比之下,Perl 的反引号运算符扩展到命令的整个输出,包括所有换行符。 (3认同)

Ser*_*nyy 9

引用自 bash 手册页,部分Command Substitution

嵌入的换行符不会被删除,但它们可能会在分词过程中被删除。

再远一点,同一部分:

如果替换出现在双引号内,则不会对结果执行分词和路径名扩展。

这就是为什么echo "$(cat /etc/passwd)" 有效。

此外,应该注意的是,按 POSIX 规范进行的命令替换会删除尾随换行符:

$ echo "$(printf "one\ntwo\n\n\n")"
one
two
Run Code Online (Sandbox Code Playgroud)

因此,通过 via 输出文件$(cat file.txt)可能会导致尾随换行符丢失,如果优先考虑整个文件的完整性,这可能会成为问题。


小智 7

您可以保留换行符,例如通过将 IFS 设置为空:

$ IFS=
$ a=$(cat links.txt)
$ echo "$a"
link1
link2
link3
Run Code Online (Sandbox Code Playgroud)