【问题标题】:Why reference $? explicitly为什么引用 $?明确的
【发布时间】:2023-03-22 09:30:01
【问题描述】:

很多sh代码长这样:

$cmd 如果 [ $? = 0];然后 $cmd2;菲

代替:

如果 $cmd;然后 $cmd2;菲

我通常假设人们使用前者只是因为他们不知道后者的语法是有效的,但我想知道是否还有其他原因(尽管想到的唯一可能性是可移植性)。有什么理由更喜欢明确引用 ${?}?

【问题讨论】:

  • 或者,甚至更短:$cmd && $cmd2

标签: shell sh


【解决方案1】:

如果您确实想将错误代码用于某些事情(记录、处理预期错误等),则必须引用 $?。对于您提到的特定场景,第二个if 构造更清晰、更短,我认为没有理由不使用它。

【讨论】:

    【解决方案2】:

    在我看来,因为很多人没有意识到你可以或多或少地像你一样测试命令的状态。同样,人们也没有意识到你可以写:

    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 -ecmd1 && cmd2 会做一些不同的事情(至少在 bash 下)。
    • @Dave Hinton:我尝试了(set -e; false && echo What?; echo OK)(false && echo What?; echo OK),都尽职尽责地回应了OK。我从您的评论中怀疑您希望前者保持沉默。
    【解决方案3】:

    因为您正在测试命令的状态标志,而不是测试命令的输出。

    如果一个命令打印到标准输出,但设置了一个标志,你会得到与你给出的两个例子不同的结果。

    经过测试,我认为是正确的。我想我记得几年前在 solaris 上遇到过问题(在 ksh 下?),但除了测试之外,我无法在我目前可以访问的机器下重新创建:

    如果 [$cmd]

    【讨论】:

    • 我的理解是$cmd的退出状态在两种编码风格下都经过了测试,并且stdout/stderr都不受它们的干扰。请举例说明在不同编码风格下给出不同行为的命令?
    • 你能举一个你第二句话的例子吗?因为不 - 结果是一样的。
    • -1:这是不正确的。试试这个...$ failcmd(){ echo "this command sucks"; return 1; }; if failcmd; then echo success; else echo fail; fi
    • 'if [ $cmd ]' 测试与问题完全不同。它根本不执行 $cmd;它只是对其内容进行某种测试——实际测试取决于内容。
    【解决方案4】:

    是的,很多人不知道后一种更优雅的形式。 我之前在以下文章中提到过这一点: http://www.pixelbeat.org/programming/shell_script_mistakes.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      相关资源
      最近更新 更多