$?
测试后是否可以保持最后一个命令的退出状态 ( ) 不变?
例如,我想做:
command -p sudo ...
[ $? -ne 1 ] && exit $?
最后一个exit $?
应该返回 sudo 退出状态,但它总是返回0
(测试的退出代码)。
是否可以在没有临时变量的情况下做到这一点?
另一个进一步澄清的例子:
spd-say "$@"
[ $? -ne 127 ] && exit $?
在这种情况下,我只想在找到第一个命令时退出(退出代码!= 127
)。我想使用实际的spd-say
退出代码退出(可能不是
0
)。
编辑:我忘了提及,我更喜欢 POSIX 兼容的解决方案,以获得更好的可移植性。
我在脚本中使用此构造,我想为同一命令提供替代方案。例如,参见我的crc32 脚本。
临时变量的问题是它们可能会隐藏其他变量,并且为了避免必须使用长名称,这不利于代码的可读性。
答案1
根据实际需求,有多种选项可以可靠地处理退出状态而无需额外开销。
您可以使用变量保存退出状态:
command -p sudo ...
rc=$?
[ "$rc" -ne 1 ] && echo "$rc"
可以直接查看成功或失败:
if command -p sudo ...
then echo success
else echo failure
fi
或者使用case
构造来区分退出状态:
command -p sudo ...
case $? in
(1) ... ;;
(127) ... ;;
(*) echo $? ;;
esac
问题中提出的特殊情况:
command -p sudo ...
case $? in (1) :;; (*) echo $?;; esac
所有这些选项的优点是它们符合 POSIX 标准。
(注意:为了便于说明,我使用了echo
上面的命令;替换为适当的exit
语句以匹配请求的功能。)
答案2
command -p ...
test 1 -ne $? && exit $_
使用$_
,它扩展为上一个命令的最后一个参数。
答案3
您可以定义(并使用)一个 shell 函数:
check_exit_status()
{
[ "$1" -ne 1 ] && exit "$1"
}
然后
command -p sudo ...
check_exit_status "$?"
$?
可以说,这是“作弊”,因为它在参数列表中复制了check_exit_status
。
这可能看起来有点尴尬,事实确实如此。 (当您对问题施加任意约束时,有时会发生这种情况。)这可能看起来不灵活,但事实并非如此。您可以变得check_exit_status
更复杂,添加参数来告诉它对退出状态值执行什么测试。
答案4
要回答你的直接问题,不,不可能保持$?
不变。这是我怀疑您关注错误问题的情况之一。临时变量是获得您想要的效果的标准且首选的方法。它是如此标准,以至于我建议放弃(或重新考虑)您认为不想使用它的任何原因;我非常怀疑任何其他方法所增加的额外复杂性是否值得。
如果您只是出于简单的好奇心而问,那么答案是否定的。