【发布时间】:2023-03-22 09:30:01
【问题描述】:
很多sh代码长这样:
$cmd 如果 [ $? = 0];然后 $cmd2;菲代替:
如果 $cmd;然后 $cmd2;菲我通常假设人们使用前者只是因为他们不知道后者的语法是有效的,但我想知道是否还有其他原因(尽管想到的唯一可能性是可移植性)。有什么理由更喜欢明确引用 ${?}?
【问题讨论】:
-
或者,甚至更短:$cmd && $cmd2
很多sh代码长这样:
$cmd 如果 [ $? = 0];然后 $cmd2;菲代替:
如果 $cmd;然后 $cmd2;菲我通常假设人们使用前者只是因为他们不知道后者的语法是有效的,但我想知道是否还有其他原因(尽管想到的唯一可能性是可移植性)。有什么理由更喜欢明确引用 ${?}?
【问题讨论】:
如果您确实想将错误代码用于某些事情(记录、处理预期错误等),则必须引用 $?。对于您提到的特定场景,第二个if 构造更清晰、更短,我认为没有理由不使用它。
【讨论】:
在我看来,因为很多人没有意识到你可以或多或少地像你一样测试命令的状态。同样,人们也没有意识到你可以写:
if cmd1
cmd2
cmd3
then
...do this after executing cmd1, cmd2 and cmd3, but ...
...only if cmd3 exits with with status 0!
fi
您还可以将代码(以简洁为代价)简化为:
cmd1 && cmd2
(我看到@shin 在评论中指出了这一点,我对此表示赞同)。
我还看到很多“Bourne”外壳代码使用:
if ( ... )
then ...
fi
有时这是合适的——但通常是 C shell 程序员写的东西,没有意识到在 Bourne shell 和衍生工具中表示“运行子 shell” - 例如 Korn shell、POSIX 兼容的 shell,和 Bash。
【讨论】:
set -e,cmd1 && cmd2 会做一些不同的事情(至少在 bash 下)。
(set -e; false && echo What?; echo OK) 和(false && echo What?; echo OK),都尽职尽责地回应了OK。我从您的评论中怀疑您希望前者保持沉默。
因为您正在测试命令的状态标志,而不是测试命令的输出。
如果一个命令打印到标准输出,但设置了一个标志,你会得到与你给出的两个例子不同的结果。
经过测试,我认为是正确的。我想我记得几年前在 solaris 上遇到过问题(在 ksh 下?),但除了测试之外,我无法在我目前可以访问的机器下重新创建:
如果 [$cmd]
【讨论】:
$cmd的退出状态在两种编码风格下都经过了测试,并且stdout/stderr都不受它们的干扰。请举例说明在不同编码风格下给出不同行为的命令?
$ failcmd(){ echo "this command sucks"; return 1; }; if failcmd; then echo success; else echo fail; fi
是的,很多人不知道后一种更优雅的形式。 我之前在以下文章中提到过这一点: http://www.pixelbeat.org/programming/shell_script_mistakes.html
【讨论】: