我是 bash 的新手,并且遇到一个问题,即在我的脚本中总是调用exit
。考虑以下简单代码:
if [[ "$x" -ge 1 && "$x" -le 4 ]]; then
/export/home/scripts/script1.sh
"$x"
|| echo "Error.. something went wrong." && exit 1
fi
考虑到错误优先于||
,我如何处理&&
错误?
使用 GNU bash,版本 3.2.51(1(。
谢谢
你可以这样做:
if [[ "$x" -ge 1 && "$x" -le 4 ]]; then
/export/home/scripts/script1.sh
"$x"
|| { echo "Error.. something went wrong." && exit 1 ; }
fi
注意:我用了{ ; }
,而不是()
,因为()
会在子shell中打开你的命令,所以它不会退出。
&&
和||
在 shell 中具有相同的优先级;隐式括号是(a || b) && c
,而不是a || (b && c)
。在同一列表中混合||
和&&
很少是一个好主意;使用显式if
语句。
if [[ "$x" -ge 1 && "$x" -le 4 ]]; then
if ! /export/home/scripts/script1.sh "$x"; then
echo "Error.. something went wrong"
exit 1
fi
fi
对于算术比较,为了提高可读性,首选算术命令((...))
而不是[[ ... ]]
。
if (( x >= 1 && x <= 4 )); then
您可以使用大括号重新组合命令,而无需创建新的子外壳:
{ true || false; } && echo true || echo false # echoes true
{ false || false; } && echo true || echo false # echoes false
它的语法非常烦人:左大括号后面必须跟一个空格(或$IFS
的另一个字符,例如换行符或制表符(,右大括号前面必须有一个换行符或一个;
,表示块的最后一个命令的结束。
括号没有这些困难,但它们会在子壳中执行它们的指令,这还有多种其他效果:
- 调用
exit
只会退出子 shell,而不是运行脚本的 shell:(exit)
是无操作 - 更新变量将只应用于子外壳,对脚本已知的值没有影响:
a=0;( (( a++ )) ; echo $a) ; echo $a
将从子外壳回显 1,然后从外壳回显 0。
我更喜欢使用if
对脚本进行显式测试,以便在事情变成梨形时我可以自己清理。也有助于保持代码看起来更干净。
if [[ "$x" -ge 1 && "$x" -le 4 ]]; then
if ! /export/home/scripts/script1.sh "$x"; then
err="Error.. something went wrong."
test -t 0 && echo "$err" >&2 # send errors to stderr if on terminal
logger -p local0.critical -t $(hostname -s) "$err" # send to syslog
# You could even add some code here to clean up after script1.sh.
exit 1
fi
fi