shell 斜杠分号等于换行符不完全正确?

uxh89sit  于 2023-02-09  发布在  Shell
关注(0)|答案(4)|浏览(113)

我在多篇文章中读到过类似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特有的问题吗?

camsedfj

camsedfj1#

看看for/do循环的语法,

for name [ [in [words …] ] ; ] do commands; done

我们可以看到do后面紧跟着 * commands *,所以在do后面使用换行符并不是替换分号,而是替换空格。
复合命令的说明还指出
在大多数情况下,复合命令描述中的命令列表可以用一个或多个换行符与命令的其余部分分隔开,并且可以用换行符代替分号。
但是没有任何地方说你可以插入随机分号。“每个换行符都可以用分号替换”简直是一个太笼统的说法,不正确。
更多人工证据:在关于命令列表的部分中,它说(着重号是我的):
list是一个或多个管道的序列,这些管道由;&&&||中的一个操作符分隔,并且可选地由;&newline中的一个终止。
在这些列表运算符中,&&||具有相同的优先级,其次是具有相同优先级的;&

list中可能出现一个或多个换行符序列,以分隔命令,相当于分号。

因此,换行符相当于命令列表中的分号。

agxfikkp

agxfikkp2#

这不仅仅是do的问题在许多情况下,shell允许在不允许分号的地方使用换行符。
以下是其中的大部分(省略了换行符或引号内分号的使用,它们总是彼此不同):
1.在&&||之后

some_command &&
some_other_command

1.管道后(|):

some_producer |
some_consumer

1.在for语句中的in之前:

for x
in $(produce_values); do

虽然空命令是非法的,但是shell语法允许在for命令中使用空值列表,所以for x in; do do_something; done是合法的,并且用换行符代替分号也是合法的。

  1. case语句中in之前或之后;同样在每个模式的关闭)和关闭每个案例的;;之后:
case $x
in
pattern)
  do_something ;;
esac

1.在关键字ifthenelifelsewhileuntil之后:

if
  some_condition
then
  do_something
else
  do_something_else
fi

1.在{((用于打开复合命令或子shell)之后:

{
   a_command
   another_command
}

(
   a_command
   another_command
)

类似地,在开始命令替换的$(之后:

a=$(
  echo hello
)

在bash中,这也适用于(进程中替换:<(...)。bash扩展在处理条件和算术替换时略有不同,请参见下文。
1.在函数定义中的)之后:

my_function()
{
  do_something
}

1.在终止命令的;&之后:

do_something;
do_something_in_background &

(Note空命令是非法的,因此do_something; ;将被拒绝。)
我从Posix标准的shell语法中得到了这个列表,Bash允许在其他地方换行;写这个答案的时候我想不出来,但是@BenjaminW提醒了我:

  • 在带括号的数组常量中,无论是数组赋值还是数组声明,换行符都被视为空白:
a+=(
  first_thing
  second_thing
)

local -A b=(
  [x]="value of x"
  [y]="value of y"
)

然后我想起了其他一些伪引用的环境:

  • Bash还接受换行符作为算术表达式中的空格:
i=$((
   i + 
     3 * j
))

if ((
  i + 3 * j
  >
  9
))

[[样式条件语句中[[之后或]]之前:

if
[[
      $a -eq "done"
]]    
then break
fi
drnojrws

drnojrws3#

"Benjamin W."在一个相当详尽而冗长的回答中所解释的,可以归纳为一个简洁而简单的一般规律,我认为这也揭示了误解这一现象背后的原因。需要记住的是:

在巴什

每个分号都可以替换为换行符

但是

每个换行符都不能替换为分号

这里,do <command>是原始语法。* 换行符 * 可以替换空格,但是由于分号不能替换换行符,因此我们不能在这里放置 * 分号 *。但是对于语法command1 ; command2换行符可以替换分号,并给予

command1
command2

随着时间的推移,我们越来越熟悉换行符作为命令行分隔符,而不是分号,并且倾向于将分号视为换行符的替代品,以便生成一行程序,但似乎bash实际上是以相反的方式设计的:分号是最初的分隔符,换行符只是语法上的糖(在命令行分隔符的上下文中)。
注:根据本杰明W.

agxfikkp

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;

相关问题