为了账号安全,请及时绑定邮箱和手机立即绑定

将stdout和stderr捕获到不同的变量中

将stdout和stderr捕获到不同的变量中

HUX布斯 2019-09-02 15:42:42
是否可以在不使用临时文件的情况下在不同的变量中存储或捕获stdout和stderr ?现在我这样做是为了out在err运行时获取stdout 和stderr some_command,但是我想避开临时文件。error_file=$(mktemp)out=$(some_command 2>$error_file)err=$(< error_file)rm $error_file
查看完整描述

3 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

好吧,它有点难看,但这是一个解决方案:


unset t_std t_err

eval "$( (echo std; echo err >&2) \

        2> >(readarray -t t_err; typeset -p t_err) \

         > >(readarray -t t_std; typeset -p t_std) )"

其中(echo std; echo err >&2)需要通过实际的命令来代替。的输出标准输出被保存到数组中$t_std由线省略换行符(线-t)和标准错误入$t_err。


如果你不喜欢数组,你可以做


unset t_std t_err

eval "$( (echo std; echo err >&2 ) \

        2> >(t_err=$(cat); typeset -p t_err) \

         > >(t_std=$(cat); typeset -p t_std) )"

它几乎模仿了var=$(cmd)除了$?我们最后一次修改的值之外的行为:


unset t_std t_err t_ret

eval "$( (echo std; echo err >&2; exit 2 ) \

        2> >(t_err=$(cat); typeset -p t_err) \

         > >(t_std=$(cat); typeset -p t_std); t_ret=$?; typeset -p t_ret )"

这里$?保存成$t_ret


使用GNU bash,版本4.2.37(1)-release(i486-pc-linux-gnu)在Debian wheezy上测试。


查看完整回答
反对 回复 2019-09-02
?
开满天机

TA贡献1786条经验 获得超13个赞

作为参考,这是ksh93技巧。(需要非古代版本)。


function out {

    echo stdout

    echo stderr >&2

}


x=${ { y=$(out); } 2>&1; }

typeset -p x y # Show the values

产生


x=stderr

y=stdout

该${ cmds;}语法只是一个命令替换不创建一个子shell。这些命令在当前的shell环境中执行。开头的空间很重要({是一个保留字)。


内部命令组的Stderr被重定向到stdout(因此它适用于内部替换)。接下来,stdout out被分配给y,并且重定向的stderr被捕获x,而没有通常丢失y到命令替换的子shell。


在其他shell中是不可能的,因为捕获输出的所有构造都需要将生成器放入子shell中,在这种情况下,它将包括赋值。


更新:现在也受mksh支持。


查看完整回答
反对 回复 2019-09-02
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

此命令在当前运行的shell中设置stdout(stdval)和stderr(errval)值:


eval "$( execcommand 2> >(setval errval) > >(setval stdval); )"

如果已定义此功能:


function setval { printf -v "$1" "%s" "$(cat)"; declare -p "$1"; }

将execcommand更改为捕获的命令,无论是“ls”,“cp”,“df”等。


所有这些都是基于我们可以在函数setval的帮助下将所有捕获的值转换为文本行的想法,然后setval用于捕获此结构中的每个值:


execcommand 2> CaptureErr > CaptureOut

将每个捕获值转换为setval调用:


execcommand 2> >(setval errval) > >(setval stdval)

将所有内容包装在执行调用中并回显它:


echo "$( execcommand 2> >(setval errval) > >(setval stdval) )"

您将获得每个setval创建的声明调用:


declare -- stdval="I'm std"

declare -- errval="I'm err"

要执行该代码(并设置vars),请使用eval:


eval "$( execcommand 2> >(setval errval) > >(setval stdval) )"

最后回应设置的变量:


echo "std out is : |$stdval| std err is : |$errval|

还可以包括return(exit)值。

完整的bash脚本示例如下所示:


#!/bin/bash --


# The only function to declare:

function setval { printf -v "$1" "%s" "$(cat)"; declare -p "$1"; }


# a dummy function with some example values:

function dummy { echo "I'm std"; echo "I'm err" >&2; return 34; }


# Running a command to capture all values

#      change execcommand to dummy or any other command to test.

eval "$( dummy 2> >(setval errval) > >(setval stdval); <<<"$?" setval retval; )"


echo "std out is : |$stdval| std err is : |$errval| return val is : |$retval|"


查看完整回答
反对 回复 2019-09-02
  • 3 回答
  • 0 关注
  • 837 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信