dje*_*lin 41 bash stdout pipe stream stderr
我知道这个语法
var=`myscript.sh`
Run Code Online (Sandbox Code Playgroud)
要么
var=$(myscript.sh)
Run Code Online (Sandbox Code Playgroud)
将捕获结果(stdout)myscript.sh转化为var.我可以重定向stderr到stdout,如果我想同时捕获.如何将它们中的每一个保存为单独的变量?
我在这里的用例是如果返回代码非零,我想要回显stderr并禁止其他方式.可能有其他方法可以做到这一点,但这种方法似乎可行,如果它实际上是可能的.
gni*_*urf 44
有一个非常丑陋的方式来捕捉stderr和stdout在没有临时文件两个单独的参数(如果你喜欢管道),使用过程中替换,source和declare适当的.我会打电话给你banana.您可以使用函数模仿这样的命令:
banana() {
echo "banana to stdout"
echo >&2 "banana to stderr"
}
Run Code Online (Sandbox Code Playgroud)
我假设你想要的标准输出banana变量bout的标准误差banana的变量berr.这是实现这一目标的魔力(仅限Bash≥4):
. <({ berr=$({ bout=$(banana); } 2>&1; declare -p bout >&2); declare -p berr; } 2>&1)
Run Code Online (Sandbox Code Playgroud)
那么,这里发生了什么?
让我们从最内层的术语开始:
bout=$(banana)
Run Code Online (Sandbox Code Playgroud)
这只是分配给bout标准输出的标准方法banana,即终端上显示的标准错误.
然后:
{ bout=$(banana); } 2>&1
Run Code Online (Sandbox Code Playgroud)
仍将分配给boutstdout banana,但stderr banana通过stdout显示在终端上(由于重定向2>&1.
然后:
{ bout=$(banana); } 2>&1; declare -p bout >&2
Run Code Online (Sandbox Code Playgroud)
将做如上述,但也将在终端显示(通过stderr)上的内容bout与declare内置:这将很快重新使用.
然后:
berr=$({ bout=$(banana); } 2>&1; declare -p bout >&2); declare -p berr
Run Code Online (Sandbox Code Playgroud)
将分配给berrstderr banana并显示berrwith 的内容declare.
此时,您将在终端屏幕上看到:
declare -- bout="banana to stdout"
declare -- berr="banana to stderr"
Run Code Online (Sandbox Code Playgroud)
与线
declare -- bout="banana to stdout"
Run Code Online (Sandbox Code Playgroud)
通过stderr显示.
最后的重定向:
{ berr=$({ bout=$(banana); } 2>&1; declare -p bout >&2); declare -p berr; } 2>&1
Run Code Online (Sandbox Code Playgroud)
将通过stdout显示之前的内容.
最后,我们使用一个进程替换到源这些行的内容.
你也提到了命令的返回码.更改banana到:
banana() {
echo "banana to stdout"
echo >&2 "banana to stderr"
return 42
}
Run Code Online (Sandbox Code Playgroud)
我们还将banana在变量中bret包含返回代码,如下所示:
. <({ berr=$({ bout=$(banana); bret=$?; } 2>&1; declare -p bout bret >&2); declare -p berr; } 2>&1)
Run Code Online (Sandbox Code Playgroud)
您也可以不使用源代码和使用进程替换eval(并且它也适用于Bash <4):
eval "$({ berr=$({ bout=$(banana); bret=$?; } 2>&1; declare -p bout bret >&2); declare -p berr; } 2>&1)"
Run Code Online (Sandbox Code Playgroud)
而这一切是安全的,因为只有东西我们source荷兰国际集团和eval荷兰国际集团从获得declare -p而且将永远是正确转义.
当然,如果你想要一个数组中的输出(例如,mapfile如果你使用Bash≥4-否则mapfile用while- read循环替换),适应是直截了当的.
例如:
banana() {
printf 'banana to stdout %d\n' {1..10}
echo >&2 'banana to stderr'
return 42
}
. <({ berr=$({ mapfile -t bout < <(banana); } 2>&1; declare -p bout >&2); declare -p berr; } 2>&1)
Run Code Online (Sandbox Code Playgroud)
并带有返回码:
. <({ berr=$({ mapfile -t bout< <(banana; bret=$?; declare -p bret >&3); } 3>&2 2>&1; declare -p bout >&2); declare -p berr; } 2>&1)
Run Code Online (Sandbox Code Playgroud)
zb'*_*zb' 29
没有临时文件就无法捕获它们.
您可以将stderr捕获到变量并将stdout传递给用户屏幕(此处的示例):
exec 3>&1 # Save the place that stdout (1) points to.
output=$(command 2>&1 1>&3) # Run command. stderr is captured.
exec 3>&- # Close FD #3.
# Or this alternative, which captures stderr, letting stdout through:
{ output=$(command 2>&1 1>&3-) ;} 3>&1
Run Code Online (Sandbox Code Playgroud)
但是没有办法捕获stdout和stderr:
你不能做的是在一个变量中捕获stdout,在另一个变量中捕获stderr,仅使用FD重定向.您必须使用临时文件(或命名管道)来实现该文件.
anu*_*ava 15
你可以做:
OUT=$(myscript.sh 2> errFile)
ERR=$(<errFile)
Run Code Online (Sandbox Code Playgroud)
现在$OUT将具有脚本的标准输出并且$ERR具有脚本的错误输出.
一种简单但不优雅的方法:将stderr重定向到临时文件,然后将其读回:
TMP=$(mktemp)
var=$(myscript.sh 2> "$TMP")
err=$(cat "$TMP")
rm "$TMP"
Run Code Online (Sandbox Code Playgroud)
小智 7
虽然我还没有找到一种方法来捕获 stderr 和 stdout 以在 bash 中分隔变量,但我将两者发送到同一个变量 \xe2\x80\xa6
\n\nresult=$( { grep "JUNK" ./junk.txt; } 2>&1 )\nRun Code Online (Sandbox Code Playgroud)\n\n\xe2\x80\xa6 然后我检查退出状态 \xe2\x80\x9c$?\xe2\x80\x9d,并对 $result 中的数据采取适当的操作。
\n| 归档时间: |
|
| 查看次数: |
46571 次 |
| 最近记录: |