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上测试。
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支持。
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|"
添加回答
举报