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

How do I redirect output to a variable in shell?

本问题已经有最佳答案,请猛点这里访问。

我有这样的剧本

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

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

1
2
3
4
5
6
if [ $hash -ne 0 ]
  then echo KO
  exit 0
else echo -n OK
  exit 0
fi

使用$( ... )构造:

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


DR

"abc"存储到$foo中:

1
echo"abc" | read foo

但是,因为管道会产生分叉,所以在管道末端之前必须使用$foo,所以…

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

当然,所有这些其他的答案都显示出了不去做OP要求的事情的方法,但这真的让我们这些寻找OP问题的人搞砸了。

问题的答案是使用read命令。这是你的做法

1
2
3
4
5
6
7
8
9
# 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

以下是它所做的以及为什么它很重要:

  • 假设series | of | commands是一系列非常复杂的管道命令。

  • mystic_command可以接受文件的内容作为stdin而不是文件路径,但不能接受--opt参数,因此它必须作为变量输入。该命令输出修改后的内容,通常会被重定向到一个文件或通过管道传输到另一个命令。(如sedawkperl等)

  • read接受stdin并将其放入变量$string中。

  • 不需要通过括号将readmystic_command放入"子shell"中,但会使其像连续管道一样流动,就像两个命令在单独的脚本文件中的位置一样。

  • 总有一个选择,在这种情况下,与我上面的例子相比,这个选择是丑陋的和不可读的。

    1
    2
    3
    4
    5
    # 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

    我的方法完全按时间顺序和逻辑。备选方案从第4个命令开始,将命令1、2和3推送到命令替换中。

    我在这个脚本中有一个真实的例子,但是我没有把它作为上面的例子,因为它还有其他一些疯狂/混乱/分散注意力的bash魔法。


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

    这种技术使用bash的"进程替换",不要与"命令替换"混淆。

    以下是一些很好的参考资料:

    • http://www.linuxjournal.com/content/shell-process-redirection
    • http://tldp.org/ldp/abs/html/process-sub.html
    • http://tldp.org/ldp/abs/html/commandsub.html?为了比较


    我想兼容的方式是:

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

    但我更喜欢

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


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

    1
    2
    3
    4
    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函数


    你可以做到:

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

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

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


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

    然后,调用函数并将其结果赋给变量。在本例中,我将结果分配给变量health。

    1
    2
    3
    4
    5
    function ruok {
      echo ruok | nc *ip* 2181
    }

    health=echo ruok *ip*

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

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

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

    不是吗?我想您当前的任务genhash将只输出一个字符串hash,因此可能对您有用。

    我是如此的neewbie,仍然在寻找完整的输出&save into 1命令。当做。