为什么在一行中写入 shell 循环时;
后面没有字符?do
这就是我的意思。当写在多行上时,for
循环看起来像:
$ for i in $(jot 2)
> do
> echo $i
> done
在一行中:
$ for i in $(jot 2); do echo $i; done
所有折叠的线都会在;
其后出现除了对于该do
行,如果包含;
,则这是一个错误。有人可能比我聪明得多,认为这是正确的做法,但我不知道原因是什么。这对我来说似乎不一致。
循环也一样while
。
$ while something
> do
> anotherthing
> done
$ while something; do anotherthing; done
答案1
这就是该命令的语法。看复合命令
for name [ [in [words …] ] ; ] do commands; done
特别注意: do commands
大多数人将do
和commands
放在单独的行上以方便阅读,但这不是必需的,您可以编写:
for i in thing
do something
done
我知道这个问题是专门关于 shell 的,我已经链接到 bash 手册。 shell 手册中没有这样写,但在 shell 中却是这样写的斯蒂芬·伯恩撰写的文章对于字节杂志。
斯蒂芬 说:
A命令列表
;
是由换行符或(分号)分隔或终止的一系列一个或多个简单命令。此外,保留字如做和完毕通常前面有换行符或;
...依次每次命令列表如下做被执行。
答案2
while
我不知道这种语法的原始原因是什么,但让我们考虑一下循环可以在条件部分接受多个命令的事实,例如
while a=$(somecmd);
[ -n "$a" ];
do
echo "$a"
done
这里,do
需要使用关键字来区分循环的条件部分和主体。是像, and (and )do
这样的关键字,它似乎与其他关键字一致,它后面不需要分号或换行符,而是紧接在命令之前出现。while
if
then
done
另一种选择(推广到if
和while
)看起来有点难看,我们需要写例如
if; [ -n "$a" ]; then
some command here
fi
循环的语法for
非常相似。
答案3
Shell 语法是基于前缀的。它有由特殊关键字引入的子句。某些条款必须结合在一起。
一个while
循环由一个或多个测试命令组成:
test ; test ; test ; ...
以及通过一个或多个身体命令:
body ; body ; body ; ...
必须有东西告诉 shell while 循环开始。这就是这个词的目的while
:
while test ; test ; test ; ...
但接下来,事情就变得模棱两可了。哪个命令是正文的开始?必须有一些东西表明这一点,这就是do
前缀的作用:
do body ; body ; body ; ...
最后,必须有某种东西表明已经看到最后一具尸体;一个特殊的关键字 done
可以做到这一点。
这些 shell 关键字不需要分号分隔,即使在同一行也是如此。例如,如果您关闭多个嵌套循环,则可以只拥有done done done ...
.
... test ; body ...
相反,如果它们位于同一行,则分号位于它们之间。该分号被理解为终止符:它属于test
.因此,如果do
在它们之间插入关键字,则该关键字必须位于分号和 之间body
。如果它位于分号的另一侧,它将被错误地嵌入到test
命令的语法中,而不是放置在命令之间。
shell 语法最初由 Stephen Bourne 设计,灵感来自大陵五。 Bourne 非常喜欢 Algol,以至于他在 shell 源代码中使用了大量 C 宏,使 C 看起来像 Algol。你可以浏览 Unix 版本 7 中 1979 年的 shell 源代码。宏位于 中mac.h
,并且它们到处都在使用。例如语句if
呈现为IF
………… ELSE
。ELIF
FI
答案4
简短的回答,因为这是由POSIX shell 语法。do
和之间的任何内容都done
被视为一组语句,而 while;
是顺序分隔符:
for_clause : For name do_group
| For name sequential_sep do_group
| For name linebreak in sequential_sep do_group
| For name linebreak in wordlist sequential_sep do_group
do_group : Do compound_list Done
sequential_sep : ';' linebreak
| newline_list
此外,如果;
有必要,标准将明确说明这一点,并将包括sequential_sep
after Do
。