Answers:
反引号替换不是问题,而是echo
; 您必须引用该变量以使控制字符起作用:
$ var=`echo line one && echo line two`
$ echo "$var"
line one
line two
bash
执行命令,引用之前执行参数扩张有必要通知bash
要打印一个字符串并且不为4字(line
,one
,line
和two
)。尝试:echo a <many spaces> b
和echo "a <many spaces> b"
。也看一下这个答案。
即使@cyrus是正确的-它实际上并不能回答整个问题,也没有任何解释。
因此,让我们通过它。
首先确定期望的字节序列:
$ { echo a; echo b; } | xxd
0000000: 610a 620a a.b.
现在,使用命令替换(第3.5.4节)尝试捕获此字节序列:
$ x=$( echo a; echo b; )
然后,执行简单的回显以验证字节序列:
$ echo $x | xxd
0000000: 6120 620a a b.
因此,似乎第一个换行符被替换为空格,而第二个换行符则保持不变。但为什么 ?
让我们看一下这里实际发生的情况:
首先,bash将进行Shell参数扩展(第3.5.3节)
“ $”字符引入参数扩展,命令替换或算术扩展。可以将要扩展的参数名称或符号括在括号中,该括号是可选的,但用于保护要扩展的变量免受紧随其后的字符的影响,这些字符可以解释为名称的一部分。
然后bash将进行单词拆分(第3.5.7节)
Shell会扫描双引号中未出现的参数扩展,命令替换和算术扩展的结果,以进行单词拆分。
Shell将$ IFS的每个字符视为定界符,并将其他扩展的结果拆分为这些字符上的单词。如果未设置IFS或它的值正好是...
接下来,bash将其视为简单命令(第3.2.1节)
简单命令是最常遇到的命令。它只是一个由空格分隔的单词序列,由外壳程序的一个控制运算符终止(请参见定义)。通常,第一个单词指定要执行的命令,其余单词是该命令的参数。
空白空格或制表符。
最后,bash调用echo(4.2节-Bash内置命令)内部命令
...输出以空格分隔并以换行符终止的args。...
因此,总而言之,通过单词拆分除去了换行符,然后echo得到2个args,“ a”和“ b”,然后将它们输出,以空格分隔并以换行符结尾。
进行@cyrus建议的操作(并使用-n抑制换行符回显),效果会更好:
$ echo -n "$x" | xxd
0000000: 610a 62 a.b
尽管它仍然不完美,但尾随的换行符已消失。仔细查看命令替换(第3.5.4节):
Bash通过执行命令并将命令替换替换为命令的标准输出来执行扩展,并删除所有尾随的换行符。
既然清楚了换行符消失的原因,bash可能会被欺骗以保留它。为此,请在末尾添加一个附加字符串,并在使用变量时将其删除:
$ x=$( echo a; echo b; echo -n extra )
$ echo -n "${x%extra}" | xxd
0000000: 610a 620a a.b.
在输出末尾添加多余的部分,并引用变量:
$ cat /no/file/here 2>&1 | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865 cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65 re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a or directory.
$ cat /no/file/here 2>&1 | cksum
3561909523 46
$
$ var=$( cat /no/file/here 2>&1; rc=${?}; echo extra; exit ${rc})
$ echo $?
1
$
$ echo -n "${var%extra}" | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865 cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65 re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a or directory.
$ echo -n "${var%extra}" | cksum
3561909523 46