将多行输出捕获到 Bash 变量中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/613572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Capturing multiple line output into a Bash variable
提问by Parker
I've got a script 'myscript' that outputs the following:
我有一个输出以下内容的脚本“myscript”:
abc
def
ghi
in another script, I call:
在另一个脚本中,我调用:
declare RESULT=$(./myscript)
and $RESULT
gets the value
并$RESULT
获得价值
abc def ghi
Is there a way to store the result either with the newlines, or with '\n' character so I can output it with 'echo -e
'?
有没有办法用换行符或 '\n' 字符存储结果,以便我可以用 ' echo -e
'输出它?
回答by Jonathan Leffler
Actually, RESULT contains what you want — to demonstrate:
实际上, RESULT 包含您想要的内容 - 演示:
echo "$RESULT"
What you show is what you get from:
你所展示的就是你从中得到的:
echo $RESULT
As noted in the comments, the difference is that (1) the double-quoted version of the variable (echo "$RESULT"
) preserves internal spacing of the value exactly as it is represented in the variable — newlines, tabs, multiple blanks and all — whereas (2) the unquoted version (echo $RESULT
) replaces each sequence of one or more blanks, tabs and newlines with a single space. Thus (1) preserves the shape of the input variable, whereas (2) creates a potentially very long single line of output with 'words' separated by single spaces (where a 'word' is a sequence of non-whitespace characters; there needn't be any alphanumerics in any of the words).
正如评论中所指出的,不同之处在于 (1) 变量 ( ) 的双引号版本echo "$RESULT"
保留了值的内部间距,正如它在变量中表示的一样——换行符、制表符、多个空格等等——而 (2 ) 不带引号的版本 ( echo $RESULT
) 用一个空格替换一个或多个空格、制表符和换行符的每个序列。因此,(1) 保留了输入变量的形状,而 (2) 创建了一个潜在的非常长的单行输出,其中“单词”由单个空格分隔(其中“单词”是非空白字符的序列;需要'不是任何单词中的任何字母数字)。
回答by l0b0
Another pitfall with this is that command substitution— $()
— strips trailing newlines. Probably not always important, but if you really want to preserve exactlywhat was output, you'll have to use another line and some quoting:
与此另一个缺陷是,命令替换- $()
-带拖尾换行符。可能并不总是很重要,但如果你真的想准确地保留输出的内容,你将不得不使用另一行和一些引用:
RESULTX="$(./myscript; echo x)"
RESULT="${RESULTX%x}"
This is especially important if you want to handle allpossible filenames(to avoid undefined behavior like operating on the wrong file).
如果您想处理所有可能的文件名(以避免未定义的行为,例如操作错误的文件),这一点尤其重要。
回答by user2574210
In case that you're interested in specific lines, use a result-array:
如果您对特定行感兴趣,请使用结果数组:
declare RESULT=($(./myscript)) # (..) = array
echo "First line: ${RESULT[0]}"
echo "Second line: ${RESULT[1]}"
echo "N-th line: ${RESULT[N]}"
回答by Lurchman
In addition to the answer given by @l0b0 I just had the situation where I needed to both keep any trailing newlines output by the script andcheck the script's return code. And the problem with l0b0's answer is that the 'echo x' was resetting $? back to zero... so I managed to come up with this very cunning solution:
除了@l0b0 给出的答案之外,我还遇到过需要保留脚本输出的任何尾随换行符并检查脚本的返回代码的情况。l0b0 的答案的问题是“echo x”正在重置 $? 回到零......所以我设法想出了这个非常狡猾的解决方案:
RESULTX="$(./myscript; echo x$?)"
RETURNCODE=${RESULTX##*x}
RESULT="${RESULTX%x*}"
回答by user1279741
After trying most of the solutions here, the easiest thing I found was the obvious - using a temp file. I'm not sure what you want to do with your multiple line output, but you can then deal with it line by line using read. About the only thing you can't really do is easily stick it all in the same variable, but for most practical purposes this is way easier to deal with.
在尝试了这里的大多数解决方案后,我发现最简单的方法是显而易见的 - 使用临时文件。我不确定您想对多行输出做什么,但是您可以使用 read 逐行处理它。关于您真正不能做的唯一一件事就是轻松地将所有内容都放在同一个变量中,但对于大多数实际目的而言,这更容易处理。
./myscript.sh > /tmp/foo
while read line ; do
echo 'whatever you want to do with $line'
done < /tmp/foo
Quick hack to make it do the requested action:
快速破解使其执行请求的操作:
result=""
./myscript.sh > /tmp/foo
while read line ; do
result="$result$line\n"
done < /tmp/foo
echo -e $result
Note this adds an extra line. If you work on it you can code around it, I'm just too lazy.
请注意,这会添加一个额外的行。如果你研究它,你可以围绕它编码,我只是太懒了。
EDIT: While this case works perfectly well, people reading this should be aware that you can easily squash your stdin inside the while loop, thus giving you a script that will run one line, clear stdin, and exit. Like ssh will do that I think? I just saw it recently, other code examples here: https://unix.stackexchange.com/questions/24260/reading-lines-from-a-file-with-bash-for-vs-while
编辑:虽然这种情况非常好,但阅读本文的人应该知道,您可以轻松地将 stdin 压缩在 while 循环中,从而为您提供一个脚本,该脚本将运行一行、清除 stdin 并退出。像 ssh 会那样做吗?我最近才看到,这里还有其他代码示例:https: //unix.stackexchange.com/questions/24260/reading-lines-from-a-file-with-bash-for-vs-while
One more time! This time with a different filehandle (stdin, stdout, stderr are 0-2, so we can use &3 or higher in bash).
再一次!这次使用不同的文件句柄(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
you can also use mktemp, but this is just a quick code example. Usage for mktemp looks like:
您也可以使用 mktemp,但这只是一个快速代码示例。mktemp 的用法如下所示:
filenamevar=`mktemp /tmp/tempXXXXXX`
./test > $filenamevar
Then use $filenamevar like you would the actual name of a file. Probably doesn't need to be explained here but someone complained in the comments.
然后像使用文件的实际名称一样使用 $filenamevar。可能不需要在这里解释,但有人在评论中抱怨。
回答by Rahul Reddy
How about this, it will read each line to a variable and that can be used subsequently ! say myscript output is redirected to a file called myscript_output
怎么样,它会将每一行读取到一个变量中,然后可以使用!说 myscript 输出被重定向到一个名为 myscript_output 的文件
awk '{while ( (getline var < "myscript_output") >0){print var;} close ("myscript_output");}'