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
看这个,首先我可以看到这个case
以esac
结尾,这是它的反转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。