bash案例声明结尾处的“ esac”是什么意思?需要吗?


55

我发现在bash case语句的末尾出现了多个“ esac”的示例,但是我没有找到任何有关其用法的清晰文档。手册页使用了它,甚至在单词上有一个索引(https://www.gnu.org/software/bash/manual/bashref.html#index-esac),但没有定义它的用法。是结束案例陈述,最佳实践还是纯技术的必需方法?


2
索引条目用于esac精确指出其应在的位置—指向定义它并说明它是必需的行。
hobbs

@hobbs,您正确的一点是,索引指向说明其用法的行,但并未以任何方式对其进行定义,特别是与它描述使用其他字符(如“ |”)的方式相比 要么 ”;” 要么 ”;;”。既然我已经阅读了答案,那么反斜杠“ case”似乎是结束命令的事实上的标准,大多数有经验的用户都会认为这是理所当然的。
GrnMtnBuckeye

如果您没有esac它或类似的东西,您如何看待它可以说明该case语句的结尾在哪里?
Barmar

它将其定义为是所述的语法的一部分case的语句,在以同样的方式elseelif以及fi被定义为一个的语法的一部分if的语句。它本身没有任何语义,因此无话可说,但是它位于case语句定义的末尾,因此它是case语句结束的地方。case向后拼写这个事实是一种方便的好奇心,但是计算机并不在乎,它只是知道它正在寻找某个单词。
hobbs

1
@hobbs“ ...对此无话可说...”,但您只是写了一段解释,解释为什么无话可说。重要的是仅了解“ esac”的意图。这就是为什么这个问题可以直接回答,并且有很多赞成票的原因。
Angelo

Answers:


99

fifor ifdonefor一样foresac是结束case语句的必需方式。

esaccase落后的拼写,而不是像fiif落后的拼写。我不知道为什么以for块结尾的令牌不是rof


33
你的意思是为什么不od结束一个do障碍?:)
通配符

4
想象一下,\od每次您想使用该实用程序时都必须键入!这很少见,但我的观点是;)
Score_Under 16'Jan 18'23

2
使您脱离666。不客气:P。很好的答案!
TheWanderer '16

12
@Wildcard是fi,不是neht,所以以此类推,它应该是rof(或elihw),而不是od(当然,od也已经被使用)...但是,也许这是由于最自不一致的一种语言期望太多的自洽性有。
zwol

1
ROTFL没什么可说的
格哈德·d。

55

esac实际上,关键字确实是结束该case语句所必需的定界符,bash并且在Unix / Linux上使用的大多数shell(不包括该csh家族)都已结束。

最初的Bourne外壳是由以前在ALGOL68上工作的Steve Bourne创建的。这种语言发明了这种反向词技术来分隔块。

case/esac

if/fi

do/od

后者是没有更多do/oddo/done在Bourne和所有派生壳包括bash因为od已经存在的作为自创建以来(UNIX命令ö CTAL ð UMP)。

请注意,do/done功能块用任一引入forwhile,或until指令。forwhile并且until不需要被终止done就足够了。这就是为什么不需要假设rofelihw代币的原因。


6

esac”终止较早的“ case”以形成“ 代码块 ”。

在Algol68中使用它们,通常使用Introduction关键字的反向字符序列来终止外壳,例如 ( if ~ then ~ else ~ fi, case ~ in ~ out ~ esac, for ~ while ~ do ~ od ).

Edsger Dijkstra和他的Guarded Command Language之后,我将它们称为“ Guarded Blocks” 。

od大概是因为Unix的“ od”命令已经存在,所以在Bourne Shell中没有使用它。

历史:

“ Guarded Block”的想法似乎来自 ALGOL 68,例如英语:

proc days in month = (int year, month)int:

  case month in
    31,
    if year mod 4=0  year mod 1000    year mod 400=0 then 29 else 28 fi,
    31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  esac;

苏联的Algol68 LGU实施也是如此:英语中Algol68的崇高案例声明为case ~ in ~ out ~ esac,西里尔字母为выб ~ в ~ либо ~ быв

然后在1975年Edsger Dijkstra借用了Algol68的代码块作为他的“ 守卫命令语言”。例如

if a  b  max := a
| b  a  max := b
fi

大概Dijstra使用“ Guarded Blocks”来克服Algol60中实现的Dangling 其他歧义,然后用C编程语言进行了重新设计。(请参阅shift-reduce冲突。

最后-从Algol68 esac到1977年的Bourne外壳(您在那里发现esac)都是由Stephen R. Bourne提供的,他开发了早期的Algol68编译器ALGOL 68C

著名的斯蒂芬还在一个名为macro.h的“ C头文件”中使用了这些相同的保护块。

#define IF  if(
#define THEN    ){
#define ELSE    } else {
#define ELIF    } else if (
#define FI  ;}

著名的软件天才Landon Curt NollLarry Bassel于1984年在美国国家半导体公司Genix移植小组受雇时,偶然发现了Steve的macro.h代码,并努力理解其应用。因此,Landon&Larry随后创建了国际混淆C代码竞赛 ...

从1984年到今天,还有数千种不使用Dijkstra的“防护命令”的“更好”的编程语言。macro.h现在,在IT本科生的“软件开发论文”中经常提到Steven Bourne在其中的使用,以证明他们没有上课睡觉。:-)


什么case out啊 从未见过这种语法
Dani_l

1
@Dani_l bourne shell没有采用Algol68语法。
jlliagre

他们为什么还称呼它,od即使它还没有被使用呢?那岂不是rofelihw
flarn2006 '18

采摘do ~ odif ~ ficase ~ esac仅仅意味着未来本科生无尽的世代能够思考Algol68的,并添加Algol68的一个简单的“批判”到他们的最后一年的项目,而无需实际编写更多然后一个网页的代码Algol68的(行?)。
NevilleDNZ

1

是的,这是必需的。正如Jacob所指出的,其逻辑与if/ 相同fi。传统的C注释分隔符/*,并*/也同样配对。因为编写C的目的是使Unix可以主要用C编写,而汇编代码最少,并且C和Unix开发团队之间有很大的重叠,所以可以合理地假设一个通用来源是闭包等效于multi -字符块定界符应以相反的顺序是相同的字符序列。

相反,像for,,while和这样的循环until使用do... done而不是反转字符顺序,因此存在一些不一致之处。


3
语法来自Bourne,它再次受到ALGOL的启发。
Runium
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.