下面的代码最好地描述了这种情况。为什么最后一行不输出尾随换行符?每行的输出都显示在注释中。我在用着GNU bash,版本 4.1.5
echo -n $'a\nb\n' | xxd -p # 610a620a
x=$'a\nb\n' ; echo -n "$x" | xxd -p # 610a620a
echo -ne "a\nb\n" | xxd -p # 610a620a
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p # 610a62
答案1
命令替换函数$()
(及其近亲反引号)专门删除尾随换行符。这是记录的行为,并且在使用该构造时应该始终注意它。
文本主体内的换行符不会被替换运算符删除,但在 shell 上进行分词时也可能会被删除,因此结果取决于您是否使用了引号。请注意这两种用法之间的区别:
$ echo -n "$(echo -n 'a\nb')"
a
b
$ !! | xxd -p
610a62
$ echo -n $(echo -n 'a\nb')
a b
$ !! | xxd -p
612062
在第二个示例中,输出没有被引用,换行符被解释为分词,使其在输出中显示为空格!
答案2
使用命令替换时,shell 在子 shell 中执行命令,返回其标准输出。在此过程中,IFS 字符失去了它们的意义(如果它们没有被引用),因为命令返回简单的分割词,因此尾随的字符被删除。例如:
$ echo "$(echo -e '\n')" | wc
1 0 1
$ echo -e '\n' | wc
2 0 2
更实际的是,pwd
即使您的目录名称之间有换行符,也会起作用,但$(pwd)
不会。
通常的解决方法是在命令末尾添加一些内容,然后删除它。