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

abc
def
ghi


在另一个脚本中,我称之为: >
$RESULT会得到值

declare RESULT=$(./myscript)

用'echo -e'输出吗?

评论

这让我感到惊讶。您没有$(cat ./myscipt)吗?否则我会期望它尝试执行命令abc,def和ghi

@litb:是的,我想是这样;您还可以使用$(<./ myscript)避免执行命令。

(注意:上面的两个注释指的是该问题的修订版,开始时我有一个脚本“ myscript”,其中包含以下内容,从而导致了这些问题。该问题的当前修订版(我有一个脚本“ myscript'(输出以下内容)使注释变得多余,但是,修订是在2011年11月11日发布的,这两个注释已经很久了。

#1 楼

实际上,RESULT包含您想要的内容-进行演示:

echo "$RESULT"


显示的内容是您从中获得的:

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

评论


@troelskn:区别在于(1)变量的双引号版本保留值的内部间距,该值与变量,换行符,制表符,多个空格以及所有变量中所表示的值完全相同,而(2)未引用的版本替换一个或多个空格,制表符和换行符的每个序列,并用一个空格隔开。因此,(1)保留输入变量的形状,而(2)创建一个可能很长的单行输出,其中“单词”由单个空格分隔(其中“单词”是非空白字符的序列;需要不能是任何字母数字)。

–乔纳森·莱弗勒(Jonathan Leffler)
2011年4月12日在1:03

为了使答案更易于理解:答案告诉echo“ $ RESULT”保留换行符,而echo $ RESULT则不保留换行符。

–于申
2012年7月14日10:15



在某些情况下,这无法保留换行符和开头的空格。

– ComaToast
16年8月13日在5:51

@CommaToast:您要详细说明吗?尾随换行符丢失;周围没有简单的方法。前导空白-我不知道在任何情况下它们会丢失。

–乔纳森·莱弗勒(Jonathan Leffler)
16年8月13日在6:11

另请参见何时将引号括在shell变量周围?

–tripleee
17年3月13日在9:39



#2 楼

这样做的另一个陷阱是命令替换-$()-删除尾随的换行符。可能并不总是很重要,但是如果您真的想保留输出的内容,则必须使用另一行并加上一些引号:如果要处理所有可能的文件名(以避免发生诸如对错误文件进行操作之类的未定义行为)。

评论


我不得不用一个坏掉的外壳工作了一段时间,它没有从命令替换中删除最后一个换行符(它不是进程替换),并且它几乎破坏了所有东西。例如,如果您做了pwd =`pwd`; ls $ pwd / $ file,在/之前有换行符,并且用双引号将名称引起来没有帮助。它很快修复。这是在1983-5年ICL Perq PNX上的时间范围; shell没有$ PWD作为内置变量。

–乔纳森·莱弗勒(Jonathan Leffler)
2013年12月29日17:59



#3 楼

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

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


评论


如果行中有空格,这将计算字段(空格之间的内容)而不是行。

–利亚姆
15年4月15日在14:00

您将使用readarray和进程替换而不是命令替换:readarray -t RESULT <<(./ myscript>。

–chepner
16年1月18日在18:44

#4 楼

除了@ l0b0给出的答案外,我只是需要保持脚本输出的所有尾随换行符并检查脚本的返回码。
l0b0的答案的问题是'echo x正在重置$?归零...所以我设法提出了一个非常巧妙的解决方案:

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


评论


这很可爱,实际上我有一个用例,我想拥有一个可以接受任意退出代码和可选消息的die()函数,并且我想使用另一个use()函数提供消息,但是换行符不断压扁,希望这可以让我解决这个问题。

–dragon788
18-09-25在22:43

#5 楼

在这里尝试了大多数解决方案之后,我发现最容易的事情是显而易见的-使用临时文件。我不确定要对多行输出进行处理,但是可以使用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


请注意,这会增加一行。如果您使用它,可以在它周围编写代码,我太懒了。在while循环中输入您的stdin,从而为您提供一个脚本,它将运行一行,清除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或更高版本)。

,但这只是一个快速的代码示例。 mktemp的用法如下:

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


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

评论


我也尝试了其他解决方案,根据您的第一个建议,我终于使脚本工​​作了

– Kar.ma
16年9月9日在15:04

Downvote:这过于复杂,无法避免多个常见的bash陷阱。

–tripleee
17年3月13日在9:39

是的,前几天有人告诉我有关stdin filehandle怪异问题的消息,我就像“哇”。 Lemme很快就添加了一些东西。

–user1279741
17年3月13日在20:21



在Bash中,您可以使用读取命令扩展名-u 3来读取文件描述符3。

–乔纳森·莱弗勒(Jonathan Leffler)
18年8月10日在16:41

除了@JonathanLeffler注释之外,您还可以编写:在读取-ru $ testout行时;回显“使用$ line做某事”;完成{testout} <<(./ test)而不是创建临时文件!

– F. Hauri
10月15日在8:46



#6 楼

解析多个输出
简介
,因此您的myscript输出3行,可能看起来像:脚本(不需要路径./),但是输出相同。
myscript() { echo $'abc\ndef\nghi'; }

考虑结果代码

要检查结果代码,测试功能将变为:
myscript() { local i; for i in abc def ghi ;do echo $i; done ;}

1。将多个输出存储在一个变量中,显示换行符

您的操作是正确的:
myscript
abc
def
ghi

关于结果代码,您可以添加:
myscript() { local i;for i in abc def ghi ;do echo $i;done;return $((RANDOM%128));}

偶在同一行:
RESULT=$(myscript)

然后
RCODE=$?

,但要显示变量定义,请使用declare -p
RESULT=$(myscript) RCODE=$?

2。使用mapfile在数组中解析多个输出

将答案存储到myvar变量中:
echo $RESULT 
abc def ghi

echo "$RESULT"
abc
def
ghi

echo ${RESULT@Q}
$'abc\ndef\nghi'

printf "%q\n" "$RESULT"
$'abc\ndef\nghi'

显示$myvar
declare -p RESULT
declare -- RESULT="abc
def
ghi"

考虑结果代码

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

read解析多个输出
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 /)


评论


查看有关帮助阅读和帮助Mapfile的有关换行符,反斜杠和其他特殊功能的选项!

– F. Hauri
10月15日上午10:21

#7 楼

怎么样,它将每行读入一个变量,并且可以随后使用!

评论


好吧,那不是bash,那是awk。

–vadipp
13年2月8日在7:29