Capturing multiple line output into a Bash variable
我有一个脚本'myscript',输出如下:
1 2 3 | abc def ghi |
在另一个脚本中,我打电话给:
1 | declare RESULT=$(./myscript) |
并且
1 | abc def ghi |
有没有办法用换行符或' n'字符存储结果,所以我可以用'
实际上,RESULT包含你想要的 - 展示:
1 | echo"$RESULT" |
你展示的是你得到的:
1 | echo $RESULT |
正如评论中所指出的,区别在于:(1)变量的双引号版本(
另一个缺陷是命令替换 -
1 2 | RESULTX="$(./myscript; echo x)" RESULT="${RESULTX%x}" |
如果要处理所有可能的文件名(以避免在错误的文件上操作等未定义的行为),这一点尤为重要。
如果您对特定行感兴趣,请使用结果数组:
1 2 3 4 | declare RESULT=($(./myscript)) # (..) = array echo"First line: ${RESULT[0]}" echo"Second line: ${RESULT[1]}" echo"N-th line: ${RESULT[N]}" |
除了@ l0b0给出的答案之外,我还有这样的情况:我需要保留脚本输出的任何尾随换行符并检查脚本的返回码。
而l0b0的答案问题是'echo x'正在重置$?回到零...所以我设法提出了这个非常狡猾的解决方案:
1 2 3 | RESULTX="$(./myscript; echo x$?)" RETURNCODE=${RESULTX##*x} RESULT="${RESULTX%x*}" |
怎么样,它会读取变量的每一行,然后可以使用!
说myscript输出被重定向到一个名为myscript_output的文件
1 | awk '{while ( (getline var <"myscript_output") >0){print var;} close ("myscript_output");}' |
在这里尝试了大部分解决方案之后,我发现的最简单的事情是显而易见的 - 使用临时文件。我不确定你想用你的多行输出做什么,但你可以使用read逐行处理它。关于你唯一不能真正做到的事情就是把它全部放在同一个变量中,但是对于大多数实际来说,这样更容易处理。
1 2 3 4 | ./myscript.sh > /tmp/foo while read line ; do echo 'whatever you want to do with $line' done < /tmp/foo |
快速入侵使其执行请求的操作:
1 2 3 4 5 6 7 | result="" ./myscript.sh > /tmp/foo while read line ; do result="$result$line " 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中使用&amp; 3或更高版本)。
1 2 3 4 5 6 7 | result="" ./test>/tmp/foo while read line <&3; do result="$result$line " done 3</tmp/foo echo -e $result |
你也可以使用mktemp,但这只是一个快速的代码示例。 mktemp的用法如下:
1 2 | filenamevar=`mktemp /tmp/tempXXXXXX` ./test > $filenamevar |
然后像使用文件的实际名称一样使用$ filenamevar。可能不需要在这里解释,但有人在评论中抱怨。