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

将多行输出捕获到Bash变量中,bash,variables,Bash,Variables,我有一个脚本“myscript”,它输出以下内容: abc def ghi 在另一个脚本中,我调用: declare RESULT=$(./myscript) 然后,$RESULT获取值 abc def ghi 是否有方法使用换行符或“\n”字符存储结果,以便我可以使用“echo-e”输出结果?事实上,结果包含您想要的内容-演示: echo "$RESULT" 你展示的就是你从中得到的: echo $RESULT 如注释中所述,区别在于(1)变量的双引号版本(echo“$RESULT

我有一个脚本“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}"

如果您想(避免在错误的文件上操作等未定义的行为),这一点尤其重要。

这一点如何,它会将每一行读取到一个变量,并随后使用该变量! 假设myscript输出被重定向到一个名为myscript_output的文件

awk '{while ( (getline var < "myscript_output") >0){print var;} close ("myscript_output");}'
awk'{while((getline变量<“myscript_输出”)>0){print var;}关闭(“myscript_输出”);}

除了@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]}"

在尝试了这里的大多数解决方案之后,我发现最简单的方法就是使用临时文件。我不确定您想对多行输出做什么,但是您可以使用read逐行处理它。你唯一不能做的事情就是把它都放在同一个变量里,但对于大多数实际情况来说,这是一种更容易处理的方法

./myscript.sh > /tmp/foo
while read line ; do 
    echo 'whatever you want to do with $line'
done < /tmp/foo
然后像使用文件的实际名称一样使用$filenamevar。这里可能不需要解释,但有人在评论中抱怨。

解析多个输出 介绍 因此,您的
myscript
输出3行内容可能如下所示:

myscript() { echo $'abc\ndef\nghi'; }

好的,这是一个函数,不是一个脚本(不需要路径
/
),但输出是相同的

myscript
abc
def
ghi
考虑结果代码 要检查结果代码,测试功能将变为:

myscript() { local i;for i in abc def ghi ;do echo $i;done;return $((RANDOM%128));}
1.在单个变量中存储多个输出,显示换行符 您的操作是正确的:

RESULT=$(myscript)
关于结果代码,您可以添加:

RCODE=$?
即使在同一行:

RESULT=$(myscript) RCODE=$?
然后

但要显示变量定义,请使用
declare-p

declare -p RESULT
declare -- RESULT="abc
def
ghi"
2.使用
mapfile
将答案存储到
myvar
变量中:

mapfile -t myvar < <(myscript)
echo ${myvar[2]}
ghi
考虑结果代码 如果您必须检查结果代码,您可以:

RESULT=$(myscript) RCODE=$?
mapfile -t myvar <<<"$RESULT"
显示变量:

declare -p firstline secondline thirdline
declare -- firstline="abc"
declare -- secondline="def"
declare -- thirdline="ghi"
我经常使用:

{ read foo;read foo total use free foo ;} < <(df -k /)
考虑结果代码 相同的预加步骤:

RESULT=$(myscript) RCODE=$?
{ read firstline; read secondline; read thirdline;} <<<"$RESULT"

declare -p firstline secondline thirdline RCODE
declare -- firstline="abc"
declare -- secondline="def"
declare -- thirdline="ghi"
declare -- RCODE="50"
RESULT=$(myscript)RCODE=$?

{读第一行;读第二行;读第三行;}这让我很惊讶。你没有美元吗?否则我会期望它尝试执行命令abc、def和ghi@litb:是的,我想是的;您也可以使用$((注意:上面的两条注释是指问题的修订版,我有一个脚本“myscript”,其中包含以下内容,这导致了这些问题。问题的当前修订版(我有一个脚本“myscript”,输出以下内容)使注释变得多余。然而,修订是从2011年11月11日开始的,在两条注释发表很久之后。关于
$IFS
请参见@troelskn:区别在于(1)变量的双引号版本保留值的内部间距,与变量、换行符、制表符、多个空格和全部中所表示的值完全相同,而(2)无引号版本用单个空格替换一个或多个空格、制表符和换行符的每个序列。因此(1)保留输入变量的形状,而(2) 创建一个可能非常长的单行输出,其中“单词”由单个空格分隔(其中“单词”是一系列非空白字符;任何单词中都不需要任何字母数字)。为了使答案更容易理解:答案告诉echo“$RESULT”保留换行符,而echo$RESULT不保留。在某些情况下,这无法保留换行符和前导空格。@CommaToast:您要详细说明吗?尾随的换行符丢失了;这不是一个简单的解决方法。前导空格-我不知道它们丢失的任何情况。请参阅,这不是bash,这不是bash真糟糕。我不得不用一个破损的外壳工作了一段时间,但并没有从中删除最后一行换行符(事实并非如此),它几乎破坏了一切。例如,如果你做了
pwd=`pwd`;ls$pwd/$file
,你在
/
前面有一个换行符,用双引号括住这个名字也没用。它很快就被修复了。这是在1983-5年ICL Perq PNX的时间范围内;shell没有
$pwd
作为内置变量。如果有spac在行中,这将计算字段(空格之间的内容)而不是行。您将使用
readarray
并处理替换而不是命令替换:
readarray-t RESULT
。我也尝试了其他解决方案,根据您的第一个建议,我终于获得了sc
mapfile -t myvar < <(myscript)
echo ${myvar[2]}
ghi
declare -p myvar
declare -a myvar=([0]="abc" [1]="def" [2]="ghi")
RESULT=$(myscript) RCODE=$?
mapfile -t myvar <<<"$RESULT"
{ read firstline; read secondline; read thirdline;} < <(myscript)
echo $secondline
def
declare -p firstline secondline thirdline
declare -- firstline="abc"
declare -- secondline="def"
declare -- thirdline="ghi"
{ read foo;read foo total use free foo ;} < <(df -k /)
declare -p use free total
declare -- use="843476"
declare -- free="582128"
declare -- total="1515376"
RESULT=$(myscript) RCODE=$?
{ read firstline; read secondline; read thirdline;} <<<"$RESULT"

declare -p firstline secondline thirdline RCODE
declare -- firstline="abc"
declare -- secondline="def"
declare -- thirdline="ghi"
declare -- RCODE="50"