将多行输出捕获到Bash变量中

我有一个脚本'myscript'输出以下内容:

abc def ghi 

在另一个脚本中,我打电话给:

 declare RESULT=$(./myscript) 

$RESULT获取值

 abc def ghi 

有没有办法用换行符存储结果,或用'\ n'字符存储结果,所以我可以输出' echo -e '?

其实,结果包含你想要的 – 来演示:

 echo "$RESULT" 

你所展示的是你得到的东西:

 echo $RESULT 

正如注释中所指出的,区别在于(1)变量的双引号版本( echo "$RESULT" )保留了与变量中所表示的值的内部间隔 – 换行符,制表符,多个空格和所有 – 而(2)未加引号的版本( echo $RESULT )用一个空格替换一个或多个空格,制表符和换行符的每个序列。 因此,(1)保留了输入变量的形状,而(2)创建了一个潜在的非常长的单行输出,其中单词由单个空格隔开(其中“单词”是非空白字符序列;在任何单词中都不能有任何字母数字)。

另一个缺陷是命令替换 – $() – 去掉了换行符。 可能并不总是很重要,但是如果你确实想要保留输出的内容,就必须使用另一行和一些引用:

 RESULTX="$(./myscript; echo x)" RESULT="${RESULTX%x}" 

如果要处理所有可能的文件名 (这样可以避免在错误的文件上操作等未定义的行为),这一点尤其重要。

除了@ l0b0给出的答案之外,我只需要保留脚本输出的换行符, 检查脚本的返回码。 而l0b0的答案的问题是'echo x'正在重置$? 回到零…所以我设法想出了这个非常狡猾的解决方案:

 RESULTX="$(./myscript; echo x$?)" RETURNCODE=${RESULTX##*x} RESULT="${RESULTX%x*}" 

如果您对特定行感兴趣,请使用结果数组:

 declare RESULT=($(./myscript)) # (..) = array echo "First line: ${RESULT[0]}" echo "Second line: ${RESULT[1]}" echo "N-th line: ${RESULT[N]}" 

怎么样呢,它会把每一行读到一个变量中,随后就可以使用! 说myscript输出被重定向到一个名为myscript_output的文件

 awk '{while ( (getline var < "myscript_output") >0){print var;} close ("myscript_output");}' 

在尝试了大部分解决方案之后,我发现最简单的事情就是显而易见的 – 使用临时文件。 我不知道你想用你的多行输出做什么,但是你可以使用read逐行处理它。 关于你唯一不能做的事就是把它全部放在同一个变量中,但是对于大多数实际的用途来说,这样做更容易处理。

 ./myscript.sh > /tmp/foo while read line ; do echo 'whatever you want to do with $line' done < /tmp/foo 

快速入侵,使其做到要求的行动:

 result="" ./myscript.sh > /tmp/foo while read line ; do result="$result$line\n" done < /tmp/foo echo -e $result 

注意这增加了一个额外的行。 如果你工作的话,你可以用它来编码,我太懒惰了。


编辑:虽然这种情况下工作得很好,阅读此人应该知道,你可以很容易地挤出你的stdin内while循环,从而给你一个脚本,将运行一行,清除stdin,并退出。 像ssh会这样做,我认为? 我刚刚看到它,其他代码示例在这里: https : //unix.stackexchange.com/questions/24260/reading-lines-from-a-file-with-bash-for-vs-while

再来一次! 这次用不同的文件句柄(stdin,stdout,stderr是0-2,所以我们可以在bash中使用&3或更高)。

 result="" ./test>/tmp/foo while read line <&3; do result="$result$line\n" done 3</tmp/foo echo -e $result 

你也可以使用mktemp,但这只是一个简单的代码示例。 mktemp的用法如下所示:

 filenamevar=`mktemp /tmp/tempXXXXXX` ./test > $filenamevar 

然后像使用$ filenamevar那样使用文件的实际名称。 可能不需要在这里解释,但有人在评论中抱怨。