bash/zsh脚本中"case"语句的奇怪语法是什么原因?

phu*_*ehe 45 bash shell zsh case

从程序员的角度来看,shell脚本只是另一种编程语言,人们必须学习并遵守语言规则.但是,我必须承认,这种语法是我在一种常用语言中见过的最奇怪的风格.shell是否采用了它来自的较旧语言的语法?语法中是否有特殊含义/含义?

作为一个例子,这里是我从SO上的另一篇文章中获取的一个小片段

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        check_status
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac
Run Code Online (Sandbox Code Playgroud)

看看这个,首先我可以看到case结束esac,这是它的反转形式(如if结束fi).其次,我理解每个案例后面跟着一个).很公平,但为什么我;在每个声明的末尾都需要两个呢?我还会说)没有伴随的(是丑陋的.

我正在寻找有关语言历史方面的更多信息,但我也是出于技术原因而开放.

Jon*_*ler 38

每个请求:

  • 所以你能猜出为什么一个循环' for ...; do ...; done'而不是' for ...; do ...; od'?这有一个合理的理由 - 但是用于标记结尾的类似Algol的反向关键字在其他地方使用过.

回答:

  • 语法来自Bourne(Bourne shell成名).他曾在Algol工作过,并且非常喜欢在Algol上模拟一些shell语法.Algol使用反向关键字来标记构造的结尾,所以'case ... esac'是合适的.循环不以'od'结尾的原因是Unix中的命令'od' - 八进制转储.因此,使用'done'代替.

通过声誉,Bourne shell源代码是用特殊的C语言编写的宏,使它看起来像Algol.这使得它难以维护.

关于主要问题 - 为什么在case声明中的替代方案周围没有开括号(括号)- 我有几个相关的理论.

首先,回到编写Bourne shell时(20世纪70年代后期),使用标准文本编辑器 ' ed' 进行了大量编辑.它没有跳过平衡括号或其他此类符号的概念,因此不需要前导括号.此外,如果您正在编写文档,您可能会使用以下内容编组您的参数:

a) ...blah...
b) ...more...
c) ...again...
Run Code Online (Sandbox Code Playgroud)

通常省略左括号 - 该case陈述非常适合该模型.

当然,从那时起,我们已经习惯于在键入右括号时标记匹配的左括号的编辑器,因此旧的Bourne shell表示法是一种麻烦.POSIX标准使前导括号可选; 大多数类似POSIX的shell(Korn,Bash,Zsh)的现代实现都会支持它,当我不必担心像Solaris 10这样的机器的可移植性时,/ bin/sh仍然是忠实的Bourne shell不允许前导括号.(我通常使用#!/bin/kshshebang 处理它.)

  • 我会说"主要问题"是语法的起源,即Algol(在维基百科页面上找不到bash).反正好的答案:) (2认同)
  • 在"原始" Bourne shell的信息可以在Sourceforge上(和其他地方容易找到您最喜爱的搜索引擎)的[传家宝Bourne Shell中(http://heirloom.sourceforge.net/sh.html)项目中找到. (2认同)

kha*_*hik 24

使用的原因;;是单个;可以用于在一行中写入多个语句,如:

restart)
   stop; start;;
...
Run Code Online (Sandbox Code Playgroud)


Pau*_*ce. 11

Bash可以接受匹配的括号:

case "$1" in
    (start)
        start
        ;;
    (stop)
        stop
        ;;

    etc.
Run Code Online (Sandbox Code Playgroud)