Bash分号等于换行符不是真的吗?

时间:2018-06-26 02:30:24

标签: bash shell

我在多篇文章中读到,类似UNIX的shell中的分号(;)等于换行。
但是,以下内容使我感到困惑,而且我也没有运气来搜索它。

我猜想这是外壳中do的问题,但是“ bash分号”并不是最适合Google的搜索词组合。

下面是一个简单的for语句。

for i in {1..10}
do
echo "hi"
echo "bye"
done

随着许多Stack Overflow大师的发布,每个换行符都可以用分号代替。

所以..我们有以下“相同”的声明。

for i in {1..10}; do; echo "hi"; echo "bye"; done

我们得到:

-bash: syntax error near unexpected token `;'

分号到底是什么?这仅仅是do的一个独特问题吗?

2 个答案:

答案 0 :(得分:5)

看着syntax of the for/do loop

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

我们可以看到do之后紧跟 commands ,因此在do之后使用换行符不会代替分号,而是空格。

compound commands的说明也说

  

在大多数情况下,复合命令说明中的命令列表可能与一个命令的其余部分之间用一个或多个换行符分隔,并且可能会在换行符后用分号代替。

但是没有地方说您可以插入随机分号。 “每个换行符都可以用分号代替”只是一种笼统的说法,并不正确。

更多手动证据:在关于lists of commands的部分中,(强调我):

  

list是由一个或多个运算符;&&&||中的一个或多个管线组成的序列,并且可以选择由;&newline之一终止。

     

在这些列表运算符中,&&||具有相同的优先级,其次是;&,具有相同的优先级。

     

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

因此,换行符等效于命令列表中的分号

答案 1 :(得分:5)

do不是正义;在许多情况下,shell允许换行符,而不允许使用分号。

其中大多数(在引号中省略换行或分号的使用,它们总是彼此不同的):

  1. &&||之后

    some_command &&
    some_other_command
    
  2. 在管道(|)之后:

    some_producer |
    some_consumer
    
  3. in语句中for之前:

    for x
    in $(produce_values); do
    

    尽管空命令是非法的,但Shell语法确实允许在for命令中使用空值列表,因此for x in; do do_something; done是合法的,因此用换行符而不是分号写的东西也是一样。

  4. in语句中case之前或之后;在关闭每个模式的)和关闭每个案例的;;之后:

    case $x
    in
    pattern)
      do_something ;;
    esac
    
  5. 在关键字ifthenelifelsewhileuntil之后:

    if
      some_condition
    then
      do_something
    else
      do_something_else
    fi
    
  6. {(之后,打开复合命令或子外壳:

    {
       a_command
       another_command
    }
    
    (
       a_command
       another_command
    )
    

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

    a=$(
      echo hello
    )
    

    在bash中,这也适用于(进程替换中的<(...)。有关条件和算术替换的bash扩展中的处理方式,请参见下文。

  7. 函数定义中)之后:

    my_function()
    {
      do_something
    }
    
  8. ;&之后终止命令:

    do_something;
    do_something_in_background &
    

    (请注意,空命令是非法的,因此do_something; ;将被拒绝。)

我从shell grammar in the Posix standard中获得了该列表。 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