POSIX sh 是否允许第一个条件中的空复合列表和条件构造中的空条件?

cuo*_*glm 5 shell posix

阅读案例条件构造的 POSIX 规范,我看到:

case word in
    [(]pattern1) compound-list;;
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
    [[(]pattern[ | pattern] ... ) compound-list]
esac
Run Code Online (Sandbox Code Playgroud)

据我了解, 的主体中至少会有一个条件case,并且compound-list必须存在与该条件对应的条件。

我写了一个快速测试:

$ cat test.sh
case $1 in
esac

case $1 in
  .) ;;
  *) echo 1
esac
Run Code Online (Sandbox Code Playgroud)

然后:

$ for shell in /bin/*sh; do
    printf '=%-18s=\n' "$shell"
    "$shell" ./test.sh .
  done
=/bin/ash          =
=/bin/bash         =
=/bin/dash         =
=/bin/heirloom-sh  =
=/bin/ksh          =
=/bin/lksh         =
=/bin/mksh         =
=/bin/pdksh        =
=/bin/posh         =
=/bin/schily-osh   =
=/bin/schily-sh    =
=/bin/sh           =
=/bin/yash         =
=/bin/zsh          =
Run Code Online (Sandbox Code Playgroud)

/bin/heirloom-sh传家宝工具箱/bin/schily-sh and /bin/schily-osh的 Bourne 外壳,是Schily Bourne 外壳

这让我很惊讶!我所有已知的 shell 都接受了该语法。并且:

case $1 in esac
Run Code Online (Sandbox Code Playgroud)

可以在上面的所有 shell 中工作,但是ksh(那是ksh93u+在我的系统中),尽管schily 证实了它可以工作ksh88

那么它是 POSIX 允许的还是我错过了什么?

mik*_*erv 6

如果有帮助,这里是语法规则。我不擅长阅读它,但它看起来确实是允许的 - 对于每个模式 + 列表案例,还有一个模式 + 中断案例。第三个似乎表明你甚至可能完全没有模式。链接在这里


case_clause      : Case WORD linebreak in linebreak case_list    Esac
                 | Case WORD linebreak in linebreak case_list_ns Esac
                 | Case WORD linebreak in linebreak              Esac
                 ;
case_list_ns     : case_list case_item_ns
                 |           case_item_ns
                 ;
case_list        : case_list case_item
                 |           case_item
                 ;
case_item_ns     :     pattern ')'               linebreak
                 |     pattern ')' compound_list linebreak
                 | '(' pattern ')'               linebreak
                 | '(' pattern ')' compound_list linebreak
                 ;
case_item        :     pattern ')' linebreak     DSEMI linebreak
                 |     pattern ')' compound_list DSEMI linebreak
                 | '(' pattern ')' linebreak     DSEMI linebreak
                 | '(' pattern ')' compound_list DSEMI linebreak
Run Code Online (Sandbox Code Playgroud)

无论如何 - 对我来说它应该起作用是有道理的。以下工作:

x=
if $x; then $x; else echo this doesnt happen; fi
Run Code Online (Sandbox Code Playgroud)

...因为解析时命令不是空的,并且外壳有一些事情要做。我总是直接将模式与附加列表相关联。事实上,它们结合得很好。

x=0
for z in a b c d e f g
do    case $z in [abcd]) ;; $((x+=1))) ;; esac
done; echo "$x"
Run Code Online (Sandbox Code Playgroud)
3
Run Code Online (Sandbox Code Playgroud)

规范对扩展顺序和模式 - 列表关联非常清楚。我总是很自然地将两者结合起来,并认为它们或多或少是一个单一的命令。因为 shell做了一些事情,所以它可以选中那个框。它可能与 C 开关盒的工作方式有关。