我发现在 bash case 语句末尾出现了多个“esac”的示例,但我没有找到任何关于它的使用的明确文档。手册页使用了它,甚至在这个词上有一个索引(https://www.gnu.org/software/bash/manual/bashref.html#index-esac),但没有定义它的用途。这是结束案例陈述所需的方式、最佳实践还是纯技术?
答案1
fi
与forif
和done
for一样for
,esac
是结束语句所需的方式case
。
esac
向后拼写case
,就像向后fi
拼写一样if
。我不知道为什么结束块的令牌for
不是rof
。
答案2
该esac
关键字确实是结束语句所需的分隔符,并且在 Unix/Linux 上使用的大多数 shell(不包括该系列)case
中。bash
csh
原本的伯恩外壳创建者:史蒂夫·伯恩谁以前从事过算法68。这种语言发明了这种反向单词技术来分隔块。
case/esac
if/fi
do/od
后者已不再存在do/od
,但do/done
在 Bourne 和所有派生的 shell 中,包括bash
因为od
自诞生以来就已经作为 Unix 命令存在(哦克塔尔d尤姆普)。
请注意,do/done
功能块由for
、while
或until
指令引入。for
,while
并且until
不需要终止就done
足够了。这就是为什么不需要假设rof
和elihw
标记的原因。
答案3
“ esac
”终止较早的“ case
”以形成“代码块”。
在Algol68中使用它们,通常使用引入关键字的反向字符序列来终止封装,例如( if ~ then ~ else ~ fi, case ~ in ~ out ~ esac, for ~ while ~ do ~ od ).
之后我会称它们为“受保护的块”埃兹格·迪杰斯特拉和他的受保护的命令语言。
od
大概由于 Unix 的先存在而没有在 Bourne Shell 中使用“od”命令。
历史:
“Guarded Block”的想法似乎来自 阿尔戈尔 68例如英语:
proc days in month = (int year, month)int:
case month in
31,
if year mod 4=0 ∧ year mod 100≠0 ∨ 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 年,Algol68 的代码块被借用了埃兹格·迪杰斯特拉为了他的受保护的命令语言。例如
if a ≥ b → max := a
| b ≥ a → max := b
fi
据推测 Dijstra 使用“守卫块”来克服悬空的其他模糊性实施于Algol60然后重新设计C语言。 (参见转移-减少冲突。)
最后 - 来自 Algol68 - “ esac
” 进入了 1977 年伯恩外壳(你发现的地方esac
)礼貌斯蒂芬·R·伯恩他开发了一个早期的 Algol68 编译器,名为阿尔戈尔68C。
众所周知,斯蒂芬还在名为“C 头文件”的“C 头文件”中使用了这些相同的受保护块宏指令
#define IF if(
#define THEN ){
#define ELSE } else {
#define ELIF } else if (
#define FI ;}
著名的软件天才兰登·科特·诺尔和拉里·巴塞尔1984 年,他在国家半导体 Genix 移植小组工作时偶然发现了 Steve 的 Macro.h 代码,并努力理解其应用程序。于是兰登和拉里创建了国际混淆C代码大赛...
从1984年至今,已有几千其他不使用 Dijkstra 的受保护命令的“更好”编程语言。 Steven Bourne 对它们的使用macro.h
现在经常在 IT 本科生的“软件开发论文”中被引用,作为他们在讲座中没有睡觉的证据。 :-)
答案4
是的,这是必需的。正如 Jacob 上面指出的,它的逻辑与if
/相同fi
。传统的 C 注释分隔符/*
和*/
也类似地配对。因为 C 的编写是为了让 Unix 可以大部分用 C 编写,用最少的汇编代码,并且 C 和 Unix 开发团队之间有很大的重叠,所以可以合理地假设一个概念的共同来源,即多的结束等价物- 字符块定界符应该是相同字符序列的相反顺序。
相反,像for
、while
、 和 这样的循环until
使用do
...done
而不是反转字符顺序,因此有一些不一致。