有没有办法让 bash 在反引号替换中不吃换行符?
例如:
var=`echo line one && echo line two`
echo $var
line one line two
Run Code Online (Sandbox Code Playgroud)
我想要的是
var=`echo line one && echo line two` # plus some magic
echo $var
line one
line two
Run Code Online (Sandbox Code Playgroud)
cYr*_*rus 61
这不是反引号替换的问题,而是echo; 您必须引用变量才能使控制字符正常工作:
$ var=`echo line one && echo line two`
$ echo "$var"
line one
line two
Run Code Online (Sandbox Code Playgroud)
Iwa*_*amp 11
简而言之,需要的是在捕获时在输出的末尾添加后缀,在使用变量时将其删除,并始终引用变量:
# add a suffix to the end of the output when capturing it
var=$( cat /no/file/here 2>&1; echo extra)
# when using the variable, remove the suffix, and quote the variable
echo -n "${var%extra}"
Run Code Online (Sandbox Code Playgroud)
将其与以下内容进行比较,其中第二个命令的输出不会以换行符结尾。
var=$( cat /no/file/here 2>&1)
echo -n "${var}"
Run Code Online (Sandbox Code Playgroud)
首先确定预期的字节序列:
$ { echo a; echo b; } | xxd
0000000: 610a 620a a.b.
Run Code Online (Sandbox Code Playgroud)
现在,使用命令替换(第 3.5.4 节)尝试捕获此字节序列:
$ x=$( echo a; echo b; )
Run Code Online (Sandbox Code Playgroud)
然后,做一个简单的回显来验证字节序列:
$ echo $x | xxd
0000000: 6120 620a a b.
Run Code Online (Sandbox Code Playgroud)
所以看起来第一个换行符被一个空格替换了,第二个换行符保持不变。但为什么 ?
让我们看看这里实际发生了什么:
首先bash会做Shell参数扩展(3.5.3节)
'$' 字符引入了参数扩展、命令替换或算术扩展。要扩展的参数名称或符号可以用大括号括起来,这是可选的,但用于保护要扩展的变量免受紧跟其后的字符的影响,这些字符可以解释为名称的一部分。
然后 bash 将进行分词(第 3.5.7 节)
shell 扫描没有出现在双引号内的参数扩展、命令替换和算术扩展的结果以进行分词。
Shell 将 $IFS 的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符上的单词。如果 IFS 未设置,或者它的值正好是 ,...
接下来,bash 会将其视为简单命令(第 3.2.1 节)
一个简单的命令是最常遇到的那种命令。它只是由空格分隔的一系列单词,由 shell 的一个控制运算符终止(请参阅定义)。第一个单词通常指定要执行的命令,其余单词是该命令的参数。
空白 空格或制表符。
最后,bash 调用echo(第 4.2 节 - Bash 内置命令)内部命令
... 输出 args,以空格分隔,以换行符结尾。...
所以总结一下,换行符被分词删除,然后echo得到2个args,“a”和“b”,然后输出它们,用空格分隔并以换行符结尾。
执行@cyrus 建议的操作(并使用 -n 抑制 echo 中的换行符),结果会更好:
$ echo -n "$x" | xxd
0000000: 610a 62 a.b
Run Code Online (Sandbox Code Playgroud)
尽管如此,它仍然不完美,尾随的换行符不见了。仔细查看命令替换(第 3.5.4 节):
Bash 通过执行命令并用命令的标准输出替换命令替换来执行扩展,并删除任何尾随的换行符。
现在已经清楚为什么换行符消失了,bash 可能会被愚弄保留它。为此,请在末尾添加一个附加字符串,并在使用变量时将其删除:
$ x=$( echo a; echo b; echo -n extra )
$ echo -n "${x%extra}" | xxd
0000000: 610a 620a a.b.
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18019 次 |
| 最近记录: |