在 bash 4 中增加变量会触发 EXIT,但在 bash 3 中则不会
考虑这个(示例性)bash 脚本:
#!/bin/bash -e
errorExit() {
echo "" >&2
echo "ERROR (${var_scriptfilename}):" >&2
echo "An unhandled error occurred." >&2
intentionalExit 1
}
intentionalExit () {
trap - EXIT # Unregister the EXIT trap
exit $1
}
trap errorExit EXIT # Trap script errors
var_scriptfilename="$(basename "$0")"
# ==== START OF TEST ====
var_counter=0
((var_counter++))
echo "var_counter is $var_counter" >&2
# ===== END OF TEST =====
intentionalExit 0
如果我在 Cygwin 的 bash 中运行它,它会产生预期的输出:
var_counter is 1
但是,如果我在我的 Debian Squeeze 盒子(它的预期目的地)上运行它,我最终会陷入 EXIT 陷阱:
ERROR (test.increment.sh):
An unhandled error occurred.
...这是为什么?
如果我删除 -e 选项,它会在两个系统上按预期工作,但显然我想保留 -e 。
稍微麻烦一点的“通用”变体,var_counter=$(($var_counter+1))
,可以在两个 shell 上设置 -e,但我更喜欢使用第一个符号(或其他符号)看起来相似),因为在阅读代码时它显然是一个增量操作。
Cygwin bash 上的 bash --version
说:
GNU bash, version 3.2.51(24)-release (i686-pc-cygwin)
Copyright (C) 2007 Free Software Foundation, Inc.
在 Debian 上,它是:
GNU bash, Version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
我很好奇为什么会这样。有人知道这种行为的原因吗?
另外,有人知道我可以使用一种类似的方法来增加 bash 中的变量吗?
Consider this (exemplary) bash script:
#!/bin/bash -e
errorExit() {
echo "" >&2
echo "ERROR (${var_scriptfilename}):" >&2
echo "An unhandled error occurred." >&2
intentionalExit 1
}
intentionalExit () {
trap - EXIT # Unregister the EXIT trap
exit $1
}
trap errorExit EXIT # Trap script errors
var_scriptfilename="$(basename "$0")"
# ==== START OF TEST ====
var_counter=0
((var_counter++))
echo "var_counter is $var_counter" >&2
# ===== END OF TEST =====
intentionalExit 0
If I run it in Cygwin's bash it produces the intended output:
var_counter is 1
However, if I run it on my Debian Squeeze box, which is its intended destination, I end up in the EXIT trap:
ERROR (test.increment.sh):
An unhandled error occurred.
...Why is that?
If I remove the -e option it works as expected on both systems, but I want to keep -e in use, obviously.
The slightly more cumbersome "universal" variant, var_counter=$(($var_counter+1))
, works with -e being set on both shells, but I would prefer to use the first notation (or something similar-looking) since it clearly sticks out as an increment operation when reading the code.
bash --version
on the Cygwin bash says:
GNU bash, version 3.2.51(24)-release (i686-pc-cygwin)
Copyright (C) 2007 Free Software Foundation, Inc.
On Debian, it is:
GNU bash, Version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
I am intrigued as to why this is that way. Does anybody know the cause of this behavior?
Also, does anybody know of a similar-looking way to increment a variable in bash that I could use?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自 Debian 上的 bash4 联机帮助页:
还有...
所以发生的事情是
((var++))
将 var 从 0 增加到 1 并返回0,导致整体表达式返回非零,从而触发
错误退出。
现在介绍两个不同 bash 版本之间的区别:此更改
在
((
行为似乎发生在 4.0 和 4.1 之间。在 4.0((
显然没有触发 errexit。有关详细信息,请参阅此 新闻 文件。
您必须向下滚动到第 135 行左右。来自源头的变更日志
分布似乎证实了这一点。
如果您只想增加变量而不使用退出状态,
有多种方法可以做到这一点。也许其他人可以提供建议
哪个是最好的,但一些可能性是:
var="$((var+1))"
,可移植的 POSIXsh
方法((var++) ) || true
,强制语句始终为零退出状态(仅限 bash)
From the bash4 manpage on Debian:
and also ...
So what is happening is
((var++))
increments var from 0 to 1 and returns0, causing the overall expression to return non-zero, which triggers
errexit
.Now for the difference between the two different bash versions: this change
in
((
behavior seems to have occurred between 4.0 and 4.1. In 4.0((
apparently did not trigger errexit. See this NEWS file for the details.
You'll have to scroll down to line 135 or so. The Changelog from the source
distribution seems to confirm this.
If you just want a variable incremented without using the exit status,
there's multiple ways to do it. Maybe some other people could give advice
on which is the best, but some possibilities are:
var="$((var+1))"
, the portable POSIXsh
method((var++)) || true
, forcing the statement to always have a zeroexit status (bash only)