>我有一个 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 ...
如何将此命令包含在&&
链中?我试过了:
- 将
&&
紧跟在 EOF 之后。不起作用,因为 EOF 必须自己在线上。 - 将
&&
单独放置在 EOF 之后的一条线上。不起作用,因为 bash 认为我试图将&&
用作命令。 - 将
&&
放在>
重定向器之前。不起作用,因为重定向器在逻辑上是&&
-ed 命令的一部分。
澄清:
从 heredoc生成配置文件的命令后面有很多(多行(命令,所以理想情况下,我正在寻找一种解决方案,允许我将以下命令放在 heredoc 之后,这是脚本的自然流程。也就是说,我不希望在一行上内联 20+ 命令。
一行中链接命令
您可以将控制运算符&&
放在"你在这里"文档中EOF
单词的后面,并且可以链接多个命令:
cat > file <<-EOF && echo -n "hello " && echo world
它将等待您在这里文档,然后打印hello world。
例
$ cat > file <<-EOF && echo -n "hello " && echo world
> a
> b
> EOF
hello world
$ cat file
a
b
<小时 />在 heredoc 分隔符之后链接命令
现在,如果要在heredoc之后放置以下命令,可以将其分组在大括号中并继续链接命令,如下所示:
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
<小时 />使用内置的集合
如果要使用 set [-+]e
而不是带有 &&
的链接命令,则必须注意,用 set -e
和 set +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
如您所见,如果您需要在包围的命令之后继续执行命令,则此解决方案不起作用。
对命令进行分组以救援
相反,您可以对包围的命令进行分组,以便创建子外壳,如下所示:
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
因此,如果您需要在链接命令之后执行其他操作,并且想要使用内置的set
,请考虑上面的示例。
另请注意有关子外壳的以下几点:
命令替换、带括号分组的命令和异步命令在与 shell 环境重复的子 shell 环境中调用,但 shell 捕获的陷阱将重置为外壳在调用时从其父级继承的值。作为管道的一部分调用的内置命令也在子 shell 环境中执行。对子外壳环境所做的更改不会影响外壳的执行环境。
如果您使用 && 运算符只是为了在失败的命令处停止并且不继续,您可能希望用 set -e 包围代码块并用 set +e 关闭。 这样你就可以删除 &&,你的代码很可能会看起来更干净。