阅读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-osh
是Schily 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 开关盒的工作方式有关。