【问题标题】:Missing semicolon in `if (( ... )) then` and no syntax error?`if (( ... )) then`中缺少分号并且没有语法错误?
【发布时间】:2018-08-27 14:58:56
【问题描述】:

有人指出一个简单的 shell 脚本中缺少分号,我很好奇为什么它没有抛出语法错误。

完整脚本:

interval () {
    INTERVAL="$*"
    WHEN_TO_RUN=0
    while read LINE; do
        if (( $(epoch 0S) >= $WHEN_TO_RUN )) then
            echo $LINE
            WHEN_TO_RUN="$(epoch $INTERVAL)"
        fi
    done
}

有问题的行:

if (( $(epoch 0S) >= $WHEN_TO_RUN )) then

我也很困惑为什么括号使这条线正常工作,而我通常期望:

if [ $(epoch 0S) -ge $WHEN_TO_RUN ]; then

如果相关,在 OSX 上

【问题讨论】:

  • (( 是语法,而 [ 是常规命令(具有内置实现以提高性能,但语义相当于外部工具);解析器对它们的处理方式不同。
  • ...这不是特定于一般的if 语句,而是特定于(( ))
  • ...参见stackoverflow.com/questions/31255699/… 作为一个密切相关的预先存在的 SO 问题(对于更一般的主题,而不是命令分隔符语法问题)。
  • ...re:全大写命名空间,见pubs.opengroup.org/onlinepubs/9699919799/basedefs/…,记住shell和环境变量共享一个命名空间:包含小写字母的环境变量名称的命名空间是为应用程序保留。应用程序可以使用此名称空间中的名称定义任何环境变量,而无需修改标准实用程序的行为。
  • ...但是是的,shell(不幸的是)具有与 JavaScript 相同的设计错误,re: 变量是全局的,除非另有明确声明。 (顺便说一句,ksh function funcname { 语法的起源是,当第一次在 ksh 中实现时,当在这样定义的函数中使用 typeset 声明时,它默认将变量设为本地变量,而在普通 POSIX 样式 typeset 中声明的函数声明的全局变量;但是,在 bash 中,function 与 POSIX 兼容的语法相比没有任何好处。

标签: shell if-statement syntax


【解决方案1】:

(( )) 是取自 ksh 的“算术命令”扩展,允许在 shell 脚本中使用 C 风格的数学语法(POSIX 指定 $((...)) 作为扩展语法;((...)) 作为命令语法是元素这是一个扩展)。因此,它的目标是与 ksh 的实现兼容——并且毫无疑问是一个独立的命令,以)) 结尾。不像[——一个没有特殊解析时处理的常规命令[1]——它在语法上很重要(解析器必须在((内部表现不同,因此需要知道它),因此解析器知道算术命令何时结束。

在 bash 2.05 之前,命令分隔符是必需的,即使在条件上下文中也是如此。但是,这与上游 ksh 实现不兼容,因此 bash 被修改为在此上下文中明确不需要分隔符。


[1] - [ 确实在 bash 中有一个内置实现,但它只在命令调度时参与,而不是在解析时参与。 p>

【讨论】:

    猜你喜欢
    • 2012-11-19
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 2019-01-04
    • 2021-05-06
    相关资源
    最近更新 更多