在 heredoc 中使用存储为 Bash 数组的命令

Using a command stored as Bash array inside a heredoc

背景:我正在编写一个包装脚本,用于处理将我们研究人员的工作发送到我们的计算集群(其中一个使用 SLURM,另一个 Torque/PBS)。它还必须作为一些分析软件(例如 FSL)中包含的包装器脚本的替代品,以便它们可以直接与集群交互。

在用户端,脚本会这样调用:

submit_job [arguments] <command to run>

对调度程序的调用得到 assembled 并且 <command to run> 应该以提交给调度程序的小脚本结束。目前,这是这样实现的:

# In case of SLURM
sbatch <sbatch arguments> <<EOF
#!/usr/bin/env bash
srun "${@}"
EOF

但是,如果我只使用 ${@},则不会保留引号。该命令可以包含引号(例如带空格的路径),并且可以有多个命令以分号分隔(然后整个内容将被引号括起来)。我无法真正控制使用它的人和软件的组合放在那里的东西。

那么,我怎样才能得到从 A(脚本参数)到 B(变量)到 C(heredoc)的命令(可能包含引号,例如带空格的路径,可能还有用分号分隔的多个命令),不搞乱报价?

我 assemble 调度程序命令使用 Bash 数组,正如经常引用的 FAQ entry 中所推荐的那样,它工作正常。但是,虽然我可以这样做:

#/usr/bin/env bash
run=( mkdir "foo bar" )
set -x
"${run[@]}"
set +x

并创建了目录 foo bar,我不能这样做:

#/usr/bin/env bash
run=( mkdir "foo bar" )
/usr/bin/env bash <<EOF
set -x
$run[@]
"${run[@]}"
set +x
EOF

第一个创建目录 foobar,因为会发生扩展,第二个尝试 运行 mkdir foo bar.[=22,但失败了=]

那么,我还剩下什么?

提前致谢

使用 printf "%q" 转义您的参数。这是传递参数的好方法。

#/usr/bin/env bash
run=(mkdir "foo bar")
/usr/bin/env bash <<EOF
set -x
${run[@]}  # this expands into `mkdir foo bar`
$(printf "%q " "${run[@]}")  # this expands into `mkdir foo\ bar`
set +x
EOF