首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在bash中设置复合命令内的变量失败(命令组)

在bash中设置复合命令内的变量失败(命令组)
EN

Stack Overflow用户
提问于 2013-08-06 01:44:35
回答 3查看 1.5K关注 0票数 3

组命令{ list; }应该在当前shell环境中执行list。

这允许诸如变量赋值之类的事情在命令组(http://mywiki.wooledge.org/BashGuide/CompoundCommands)之外可见。

我使用它将输出发送到日志文件和终端:

代码语言:javascript
运行
复制
{ { echo "Result is 13"; echo "ERROR: division by 0" 1>&2; } | tee -a stdout.txt; } 3>&1 1>&2 2>&3 | tee -a stderr.txt;

主题“在shell脚本中通过管道将stdout和stderr连接到两个不同的进程?”点击这里阅读:pipe stdout and stderr to two different processes in shell script?

代码语言:javascript
运行
复制
{ echo "Result is 13"; echo "ERROR: division by 0" 1>&2; }

模拟输出到stdout和stderr的命令。

我也想评估一下退出状态。/bin/true/bin/false模拟可能成功也可能失败的命令。所以我尝试将$?保存到一个变量r

代码语言:javascript
运行
复制
~$ r=init; { /bin/true; r=$?; } | cat; echo $r;
init
~$ r=init; { /bin/true; r=$?; } 2>/dev/null; echo $r;
0

如您所见,上面的管道构造没有设置变量r,而第二个命令行导出了预期的结果。这是个bug,还是我的错?谢谢。

我使用以下版本的bash测试了Ubuntu12.04.2LTS (~$)和Debian GNU/Linux7.0 (wheezy) (~#):

代码语言:javascript
运行
复制
~$ echo $BASH_VERSION
4.2.25(1)-release

~# echo $BASH_VERSION
4.2.37(1)-release
EN

回答 3

Stack Overflow用户

发布于 2013-08-06 01:52:29

我认为,您错过了/bin/true Returs0和/bin/false返回1

回显$ r='res:';{/

/true;r+=$?;} 2>/dev/null;回显$r;

分辨率:0

回显$ r='res:';{/bin/

;r+=$?;} 2>/dev/null;回显$r;

分辨率:1

票数 0
EN

Stack Overflow用户

发布于 2013-08-06 01:56:39

我尝试了一个测试程序:

代码语言:javascript
运行
复制
x=0
{ x=$$ ; echo "$$ $BASHPID $x" ; }
echo $x

x=0
{ x=$$ ; echo "$$ $BASHPID $x" ; } | cat
echo $x

事实上-看起来管道将先前的代码强制到另一个进程中,但没有重新初始化bash -所以$BASHPID改变了,但$$改变了。

有关$$$BASHPID之间区别的更多详细信息,请参阅Difference between bash pid and $$

输出$BASH_SUBSHELL还会显示第二个比特正在子外壳中运行(级别1),第一个比特在级别0。

票数 0
EN

Stack Overflow用户

发布于 2013-08-06 02:44:14

bash将管道的所有元素作为子进程执行;如果它们是shell内置或命令组,这意味着它们在subshell中执行,因此它们设置的任何变量都不会传播到父shell。这通常很难解决,但如果您只需要命令组的退出状态,则可以使用$PIPESTATUS数组来获取它:

代码语言:javascript
运行
复制
$ { false; } | cat; echo "${PIPESTATUS[@]}"
1 0
$ { false; } | cat; r=${PIPESTATUS[0]}; echo $r
1
$ { true; } | cat; r=${PIPESTATUS[0]}; echo $r
0

请注意,这仅适用于获取组中最后一个命令的退出状态:

代码语言:javascript
运行
复制
$ { false; true; false; uselessvar=$?; } | cat; r=${PIPESTATUS[0]}; echo $r
0

..。因为uselessvar=$?成功了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18064352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档