阅读案例条件构造的 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 允许的还是我错过了什么?
如果有帮助,这里是语法规则。我不擅长阅读它,但它看起来确实是允许的 - 对于每个模式 + 列表案例,还有一个模式 + 中断案例。第三个似乎表明你甚至可能完全没有模式。链接在这里。
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 开关盒的工作方式有关。