如何避免bash命令替换以删除换行符?

为了加快某些bash脚本的执行,我想使用命令替换将命令的结果保存在一个变量中,但命令替换用一个空格替换0x0A换行符。例如:
a=`df -H`

要么

a=$( df -H )

当我想进一步处理$ a时,换行符被一个空格替换,所有的行现在在一行,这是更难grep:

echo $a

什么是容易的技巧,以避免换行符被命令替换删除?

不删除非尾随换行符

你正在寻找的换行符在那里,你只是不看到他们,因为你使用echo没有引用变量。

验证:

$ a=$( df -H )
$ echo $a
Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm
$ echo "$a"
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3       276G   50G  213G  19% /
udev            2.1G  4.1k  2.1G   1% /dev
tmpfs           832M  820k  832M   1% /run
none            5.3M     0  5.3M   0% /run/lock
none            2.1G  320k  2.1G   1% /run/shm
$

将删除尾随换行符

当@ user4815162342正确指出,虽然输出中的换行符没有被删除,但尾随的换行符被命令替换删除。见下面的实验:

$ a=$'test\n\n'
$ echo "$a"
test


$ b=$(echo "$a")
$ echo "$b"
test
$

在大多数情况下,这没有关系,因为echo将添加删除的换行符(除非它使用-n选项调用),但有一些边缘情况下,一个程序的输出中有一个尾随换行符,是有意义的。

解决方法

添加虚拟字符

在这种情况下,如@Scrutinizer所述,您可以使用以下解决方法:

$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test


$

说明:将字符x添加到输出(使用printf x),换行符之后。由于换行符不再跟随,它们不会被命令替换删除。下一步是使用$ {a%x}中的%运算符删除我们添加的x。现在我们有原始的输出,所有的换行符现在!

2.使用过程替代进行读取

代替使用命令替换将程序的输出分配给变量,我们可以使用process substitution将程序的输出馈送到读取内置命令(信用到@ormaaj)。过程替换保留所有换行符。读取变量的输出有点棘手,但你可以这样做:

$ IFS= read -rd '' var < <( printf 'test\n\n' ) 
$ echo "$var"
test


$

说明:

>我们将读命令的internal field separator设置为null,使用IFS =。否则读不会将整个输出分配给var,而只分配给第一个令牌。
>我们使用选项-rd”调用read。 r用于防止反斜杠作为特殊字符,并且d’将分隔符设置为无,以便读取读取整个输出,而不是仅读取第一行。

3.从管道中读取

而不是使用命令或进程替代来将程序的输出分配给变量,而是可以将程序的输出传递给读取命令(信用到@ormaaj)。管道还保留所有换行。注意,这次我们设置lastpipe shell可选行为,使用the shopt builtin.这是必需的,以便read命令在当前shell环境中执行。否则,变量将在子shell中分配,并且将无法从脚本的其余部分访问。

$ cat test.sh 
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh 
test


$

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...