【问题标题】:Using && after a heredoc in bash在 bash 中的 heredoc 之后使用 &&
【发布时间】:2015-02-02 19:00:18
【问题描述】:

我有一个 bash 脚本,我使用 && 将其命令链接在一起,因为我希望脚本在个别步骤失败时停止。

其中一个步骤是基于 heredoc 创建配置文件:

some_command &&
some_command &&
some_command &&
some_command &&
some_command &&
some_command &&
cat > ./my-conf.yml <<-EOF
host: myhost.example.com
... blah blah ...
EOF
... lots more commands ...

如何在&amp;&amp; 链中包含此命令?我试过了:

  • 在 EOF 之后立即放置 &amp;&amp;。不起作用,因为 EOF 必须自己在一条线上。
  • &amp;&amp; 单独放在EOF 之后的一行上。不起作用,因为 bash 认为我正在尝试使用 &amp;&amp; 作为命令。
  • &amp;&amp; 放在&gt; 重定向器之前。没有用,因为重定向器在逻辑上是 &amp;&amp;-ed 命令的一部分。

澄清:

从heredoc生成配置文件的命令后面有很多(多行)命令,所以理想情况下,我正在寻找一种解决方案,允许我在heredoc之后放置以下命令,这是自然的流程剧本。也就是说,我不希望在一行中内联 20 多个命令。

【问题讨论】:

    标签: bash heredoc


    【解决方案1】:

    在一行中链接命令

    您可以将control operator &amp;&amp; 紧跟在here document 中的EOF 单词之后,并且可以链接多个命令:

    cat > file <<-EOF && echo -n "hello " && echo world
    

    它将等待您的 here-document,然后打印 hello world

    示例

    $ cat > file <<-EOF && echo -n "hello " && echo world
    > a
    > b
    > EOF
    hello world
    
    $ cat file
    a
    b
    

    heredoc 分隔符后的链接命令

    现在,如果您想在heredoc 之后放置以下命令,您可以将group 放在花括号中并继续链接 命令,如下所示:

    echo -n "hello " && { cat > file <<-EOF
    a
    b
    EOF
    } && echo world
    

    示例

    $ echo -n "hello " && { cat > file <<-EOF
    > a
    > b
    > EOF
    > } && echo world
    hello world
    
    $ cat file
    a
    b
    

    使用the set built in

    如果您要使用set [-+]e 而不是链式命令&amp;&amp;,您必须注意用set -eset +e 包围一段代码不是直接替代方案,您必须注意以下事项:

    set [-+]e包围的依赖命令

    echo first_command
    false # it doesn't stop the execution of the script
    
    # surrounded commands
    set -e
    echo successful_command_a
    false # here stops the execution of the script
    echo successful_command_b
    set +e
    
    # this command is never reached
    echo last_command
    

    如您所见,如果您需要在包围命令之后继续执行命令,此解决方案不起作用。

    Grouping Commands救援

    相反,您可以对被包围的命令进行分组,以创建一个子shell,如下所示:

    echo first_command
    false # it doesn't stop the execution of the script
    
    # surrounded commands executed in a subshell
    (
    set -e
    echo successful_command_a
    false # here stops the execution of the group
    echo successful_command_b
    set +e # actually, this is not needed here
    )
    
    # the script is alive here
    false # it doesn't stop the execution of the script
    echo last_command
    

    因此,如果您需要在您的链式命令之后执行其他操作并且您想使用the set builtin,请考虑上面的示例。

    还要注意以下关于subshells

    命令替换、用括号分组的命令和异步命令在作为 shell 环境副本的子 shell 环境中调用,除了 shell 捕获的陷阱被重置为 shell 在调用时从其父 shell 继承的值.作为管道的一部分调用的内置命令也在子 shell 环境中执行。对子 shell 环境所做的更改不会影响 shell 的执行环境。

    【讨论】:

    • j.a.,感谢您添加有关 set +/-e 的额外信息。这个问题的答案真的很好。
    【解决方案2】:

    如果您使用 && 运算符只是为了在失败的命令处停止而不继续,您可能希望用 set -e 包围代码块并用 set +e 关闭。这样您就可以删除 && 并且您的代码很可能看起来更干净。

    【讨论】:

      猜你喜欢
      • 2019-03-05
      • 2021-09-28
      • 2019-08-29
      • 2019-08-05
      • 2013-07-19
      • 2023-02-01
      • 2015-01-16
      • 2016-10-28
      相关资源
      最近更新 更多