我在多篇文章中读到过类似UNIX的shell中的分号(;
)等于一个新行。
然而,下面的内容让我很困惑,我也没有运气去谷歌它。
我猜这是shell中do
的问题,但是"bash semicolon do"并不是最适合google的搜索词组合。
下面是一个简单的for
语句。
for i in {1..10}
do
echo "hi"
echo "bye"
done
正如许多栈溢出Maven所指出的,每一个换行符都可以用分号代替。
所以...我们有下面这个"相同"的陈述。
for i in {1..10}; do; echo "hi"; echo "bye"; done
我们得到:
-bash: syntax error near unexpected token `;'
分号到底是什么?这只是do
特有的问题吗?
4条答案
按热度按时间camsedfj1#
看看
for
/do
循环的语法,我们可以看到
do
后面紧跟着 *commands
*,所以在do
后面使用换行符并不是替换分号,而是替换空格。复合命令的说明还指出
在大多数情况下,复合命令描述中的命令列表可以用一个或多个换行符与命令的其余部分分隔开,并且可以用换行符代替分号。
但是没有任何地方说你可以插入随机分号。“每个换行符都可以用分号替换”简直是一个太笼统的说法,不正确。
更多人工证据:在关于命令列表的部分中,它说(着重号是我的):
list
是一个或多个管道的序列,这些管道由;
、&
、&&
或||
中的一个操作符分隔,并且可选地由;
、&
或newline
中的一个终止。在这些列表运算符中,
&&
和||
具有相同的优先级,其次是具有相同优先级的;
和&
。在
list
中可能出现一个或多个换行符序列,以分隔命令,相当于分号。因此,换行符相当于命令列表中的分号。
agxfikkp2#
这不仅仅是
do
的问题在许多情况下,shell允许在不允许分号的地方使用换行符。以下是其中的大部分(省略了换行符或引号内分号的使用,它们总是彼此不同):
1.在
&&
或||
之后1.管道后(
|
):1.在
for
语句中的in
之前:虽然空命令是非法的,但是shell语法允许在
for
命令中使用空值列表,所以for x in; do do_something; done
是合法的,并且用换行符代替分号也是合法的。case
语句中in
之前或之后;同样在每个模式的关闭)
和关闭每个案例的;;
之后:1.在关键字
if
、then
、elif
、else
、while
或until
之后:1.在
{
或(
(用于打开复合命令或子shell)之后:类似地,在开始命令替换的
$(
之后:在bash中,这也适用于
(
进程中替换:<(...)
。bash扩展在处理条件和算术替换时略有不同,请参见下文。1.在函数定义中的
)
之后:1.在终止命令的
;
或&
之后:(Note空命令是非法的,因此
do_something; ;
将被拒绝。)我从Posix标准的shell语法中得到了这个列表,Bash允许在其他地方换行;写这个答案的时候我想不出来,但是@BenjaminW提醒了我:
然后我想起了其他一些伪引用的环境:
和
[[
样式条件语句中[[
之后或]]
之前:drnojrws3#
"Benjamin W."在一个相当详尽而冗长的回答中所解释的,可以归纳为一个简洁而简单的一般规律,我认为这也揭示了误解这一现象背后的原因。需要记住的是:
在巴什
每个分号都可以替换为换行符。
但是
每个换行符都不能替换为分号。
这里,
do <command>
是原始语法。* 换行符 * 可以替换空格,但是由于分号不能替换换行符,因此我们不能在这里放置 * 分号 *。但是对于语法command1 ; command2
,换行符可以替换分号,并给予随着时间的推移,我们越来越熟悉换行符作为命令行分隔符,而不是分号,并且倾向于将分号视为换行符的替代品,以便生成一行程序,但似乎bash实际上是以相反的方式设计的:分号是最初的分隔符,换行符只是语法上的糖(在命令行分隔符的上下文中)。
注:根据本杰明W.
agxfikkp4#
他们在zsh工作:
for i in {1..10}; do; echo "hi"; echo "bye"; done
; for i in {1..10}; do; echo "hi"; echo "bye"; done
; for i in {1..10}; do; echo "hi"; echo "bye"; done;