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

从程序员的angular度来看,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 

看这个,首先我可以看到这个caseesac结尾,这是它的反转forms(就像以fi结尾)。 其次,我明白,每个案件后面都是a ) 。 够公平的,但为什么我需要两个; 在每一个陈述结束? 我也会说,没有伴随(是丑陋的。

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

每个请求:

  • 所以你可以猜测为什么一个循环是“ for ...; do ...; done for ...; do ...; done for ...; do ...; done “而不是” for ...; do ...; od for ...; do ...; od for ...; do ...; od '? 有一个合理的理由 – 但是标记结束的Algol-like关键字在其他地方使用。

回答:

  • 语法来自Bourne(Bourne shell的名气)。 他曾经在Algol上工作过,并且很喜欢在Algol上build立一些shell语法的模型。 Algol使用反向关键字来标记结构的末尾,因此“case … esac”是合适的。 循环不以'od'结尾的原因是Unix中已经有一个命令“od” – 八进制转储。 所以,用“完成”来代替。

由于声誉,Bourne shell源代码是用特殊的C语言编写的,使其看起来像Algol。 这使得难以维护。

关于主要问题 – 为什么在case陈述的备选案文中没有左括号(括号) – 我有一些相关的理论。

首先,在编写Bourne shell的时候(20世纪70年代末),使用标准的文本编辑器 ' ed '进行了很多编辑。 它没有跳过一个平衡括号或其他这样的符号的概念,所以不需要一个左括号。 另外,如果你正在编写一个文档,你可以很好地整理你的论点:

 a) ...blah... b) ...more... c) ...again... 

开头的括号通常被忽略 – case陈述很适合该模型。

当然,从那以后,我们已经习惯了编辑器,当你键入一个左括号时,标记匹配的左括号,所以旧的Bourne shell符号是一个讨厌的东西。 POSIX标准使主括号可选; 更类似POSIX的shell(Korn,Bash,Zsh)的更现代化的实现将支持这一点,当我不必担心可移植性如Solaris 10这样的机器时,我通常会使用它,因为/ bin / sh仍然是一个忠实的Bourne shell不允许使用主括号。 (我通常用#!/bin/ksh作为shebang来处理。)

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

 restart) stop; start;; ... 

Bash可以接受匹配的圆括号:

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

右括号有时用在自然语言的列表中,比如

 1) do this 2) do that 

反过来的关键字是从某种forms的Algol中获得的,但实际上是交互使用的一个非常好的主意。 他们明确划分了一个构造的结尾,包括if / else。

例如,用C语法,在parsing之后:

 if (condition) command here; 

还有else来? rc是Plan 9的一个更类似于C的语法的shell,通过提供if not不是else而不是else ,它可以解决这个问题。

使用Bourne shell语法,您可以使用else ,也可以不使用另外的input。