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

为了加速一些bash脚本的执行,我想使用命令replace将一个命令的结果保存在一个variables中,但是命令replace将0x0A换行符replace为一个空格。 例如:

 a=`df -H` 

要么

 a=$( df -H ) 

当我想进一步处理$a ,换行符会被一个空格replace,所有的行现在都在一行上,这对grep来说更加困难:

 echo $a 

避免换行符被删除的简单技巧是什么?

非尾随换行符不会被删除

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

validation

 $ 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正确指出的那样,虽然输出中的换行符不会被删除,但换行符后面的换行符会被replace掉。 看下面的实验:

 $ a=$'test\n\n' $ echo "$a" test $ b=$(echo "$a") $ echo "$b" test $ 

在大多数情况下,这并不重要,因为echo会添加除去的换行符(除非它是用-n选项调用的),但是在程序的输出中还有一些边缘情况的尾随换行符,由于某种原因是重要的。

解决方法

1.添加虚拟angular色

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

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

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

2.使用进程replace进行读取

而不是使用命令replace来将程序的输出分配给variables,我们可以改为使用进程replace来将程序的输出提供给read内置命令(记入@ormaaj )。 进程replace保留所有换行符。 读取输出到一个variables有点棘手,但你可以这样做:

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

说明:

  • 我们将读命令的内部字段分隔符设置为空,其中IFS= 。 否则, read不会将整个输出分配给var ,而只会分配第一个标记。
  • 我们用选项-rd ''调用readr用于防止反斜杠作为特殊字符,并用d ''将分隔符设置为空,以便读取读取整个输出,而不是仅读取第一行。

3.从pipe道读取

而不是使用命令或进程replace来将程序的输出分配给variables,而是将程序的输出传递给read命令(信任给@ormaaj )。 pipe道也保留所有换行符。 但是请注意,这次我们使用shopt内置的方法设置了lastpipe shell的可选行为。 这是必需的,以便read命令在当前shell环境中执行。 否则,variables将被分配在一个子shell中,并且不能从脚本的其余部分访问。

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

我试图把我的头围绕着这个,因为我正在使用bash在F#脚本上运行解释器的结果stream。 经过一些反复试验,结果发现解决了这个问题:

 $ cat fsi.ch #!/bin/bash echo "$(fsharpi --quiet --exec --nologo $1)" $ fsi.ch messages.fsx Welcome to my program. Choose from the menu: new | show | remove 

假设你当然需要运行一个terminal程序。 希望这可以帮助。