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

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

阅读case 条件构造的 POSIX 规范, 我懂了:

case word in
    [(]pattern1) compound-list;;
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
    [[(]pattern[ | pattern] ... ) compound-list]
esac

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

我写了一个快速测试:

$ cat test.sh
case $1 in
esac

case $1 in
  .) ;;
  *) echo 1
esac

然后:

$ 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          =

/bin/heirloom-sh传家宝工具箱中的 Bourne shell/bin/schily-sh and /bin/schily-oshSchily Bourne shell

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

case $1 in esac

在上面的所有 shell 中工作但是ksh(这是ksh93u+在我的系统中),尽管它ksh88经 schily 证实曾在该公司工作过

那么 POSIX 允许这样做还是我错过了什么?

答案1

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


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

无论如何 - 对我来说它应该有效。以下作品:

x=
if $x; then $x; else echo this doesnt happen; fi

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

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

3

该规范对于扩展的顺序和模式列表关联非常清楚。我总是自然地将两者结合起来,并将它们或多或少地视为一个命令。所以因为外壳某事,它可以选中该框。这可能与 C 开关盒的工作方式有关。

相关内容