bash 如何将输出重定向到 shell 中的变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2559076/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:07:35  来源:igfitidea点击:

How do I redirect output to a variable in shell?

bashshell

提问by markcial

I have a script like that

我有一个这样的脚本

genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5

I want to get stream generated by genhash in a variable. How do I redirect it into a variable $hashto compare inside a conditional?

我想在变量中获取由 genhash 生成的流。如何将其重定向到变量中$hash以在条件内进行比较?

if [ $hash -ne 0 ]
  then echo KO
  exit 0
else echo -n OK
  exit 0
fi

回答by

Use the $( ... )construct:

使用$( ... )构造:

hash=$(genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5)

回答by Bruno Bronosky

TL;DR

TL; 博士

To store "abc"into $foo:

存储"abc"$foo

echo "abc" | read foo

But, because pipes create forks, you have to use $foobefore the pipe ends, so...

但是,因为管道会产生叉子,所以你必须$foo在管道结束之前使用,所以......

echo "abc" | ( read foo; date +"I received $foo on %D"; )


Sure, all these other answers show ways to not do what the OP asked, but that really screws up the rest of us who searched for the OP's question.

当然,所有这些其他答案都显示了不做 OP 要求的方法,但这确实让我们其他搜索 OP 问题的人搞砸了。

The answer to the question is to use the readcommand.

问题的答案是使用read命令。

Here's how you do it

这是你如何做到的

# I would usually do this on one line, but for readability...
series | of | commands \
| \
(
  read string;
  mystic_command --opt "$string" /path/to/file
) \
| \
handle_mystified_file

Here is what it is doing and why it is important:

这是它正在做什么以及为什么它很重要:

  1. Let's pretend that the series | of | commandsis a very complicated series of piped commands.

  2. mystic_commandcan accept the content of a file as stdin in lieu of a file path, but not the --optargtherefore it must come in as a variable. The command outputs the modified content and would commonly be redirected into a file or piped to another command. (E.g. sed, awk, perl, etc.)

  3. readtakes stdin and places it into the variable $string

  4. Putting the readand the mystic_commandinto a "sub shell" via parenthesis is not necessary but makes it flow like a continuous pipe as if the 2 commands where in a separate script file.

  1. 让我们假设这series | of | commands是一系列非常复杂的管道命令。

  2. mystic_command可以接受文件内容作为标准输入来代替文件路径,但不能接受--optarg,因此它必须作为变量出现。该命令输出修改后的内容,通常会被重定向到一个文件或通过管道传输到另一个命令。(例如sedawkperl等等)

  3. read获取 stdin 并将其放入变量中 $string

  4. 不需要通过括号将readmystic_command放入“子外壳”中,但使其像连续管道一样流动,就好像 2 个命令位于单独的脚本文件中一样。

There is always an alternative, and in this case the alternative is ugly and unreadable compared to my example above.

总有一个替代方案,在这种情况下,与我上面的例子相比,替代方案是丑陋且不可读的。

# my example above as a oneliner
series | of | commands | (read string; mystic_command --opt "$string" /path/to/file) | handle_mystified_file

# ugly and unreadable alternative
mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file

My way is entirely chronologicaland logical. The alternative starts with the 4th command and shoves commands 1, 2, and 3 into command substitution.

我的方式完全是按时间顺序和逻辑进行的。替代方案从第 4 个命令开始,并将命令 1、2 和 3 推入命令替换中。

I have a real world example of this in this scriptbut I didn't use it as the example above because it has some other crazy/confusing/distracting bash magic going on also.

我在这个脚本中有一个真实世界的例子,但我没有将它用作上面的例子,因为它还有一些其他疯狂/令人困惑/分散注意力的 bash 魔术。

回答by Steven Penny

read hash < <(genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5)

This technique uses Bash's "process substitution" not to be confused with "command substitution".

该技术使用 Bash 的“进程替换”,不要与“命令替换”混淆。

Here are a few good references:

这里有一些很好的参考:

回答by ony

I guess compatible way:

我猜兼容的方式:

hash=`genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5`

but I prefer

但是我更喜欢

hash="$(genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5)"

回答by Huuu

If a pipeline is too complicated to wrap in $(...), consider writing a function. Any local variables available at the time of definition will be accessible.

如果管道太复杂而无法包装$(...),请考虑编写一个函数。定义时可用的任何局部变量都可以访问。

function getHash {
  genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5
}
hash=$(getHash)

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Functions

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Functions

回答by codaddict

You can do:

你可以做:

hash=$(genhash --use-ssl -s $IP -p 443 --url $URL)

or

或者

hash=`genhash --use-ssl -s $IP -p 443 --url $URL`

If you want to result of the entire pipe to be assigned to the variable, you can use the entire pipeline in the above assignments.

如果要将整个管道的结果分配给变量,则可以在上述分配中使用整个管道。

回答by m3nda

I got error sometimes when using $(`code`)constructor.

使用$(`code`)构造函数时有时会出错。

Finally i got some approach to that here: https://stackoverflow.com/a/7902174/2480481

最后我在这里找到了一些方法:https: //stackoverflow.com/a/7902174/2480481

Basically, using Tee to read again the ouput and putting it into a variable. Theres how you see the normal output then read it from the ouput.

基本上,使用 Tee 再次读取输出并将其放入变量中。这就是您如何看到正常输出然后从输出中读取它的方式。

is not? I guess your current task genhash will output just that, a single string hash so might work for you.

不是?我猜您当前的任务 genhash 将仅输出单个字符串哈希,因此可能对您有用。

Im so neewbie and still looking for full output & save into 1 command. Regards.

我是新手,仍在寻找完整的输出并保存到 1 个命令中。问候。

回答by Arena Hernandez

Create a function calling it as the command you want to invoke. In this case, I need to use the ruokcommand.

创建一个调用它的函数作为您要调用的命令。在这种情况下,我需要使用ruok命令。

Then, call the function and assign its result into a variable. In this case, I am assigning the result to the variable health.

然后,调用该函数并将其结果赋给一个变量。在这种情况下,我将结果分配给变量health

function ruok {
  echo ruok | nc *ip* 2181
}

health=echo ruok *ip*