使用在Heredoc

时间:2018-08-23 08:53:26

标签: arrays bash heredoc

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

在用户端,该脚本将这样调用:

submit_job [arguments] <command to run>

对调度程序的调用已组合,<command to run>应该以提交给调度程序的小脚本结尾。目前,这是这样实现的:

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

但是,如果我仅使用${@},则不会保留引号。该命令可以包含引号(例如,带空格的路径),并且可以有多个用分号分隔的命令(但整个内容将用引号引起来)。我真的无法控制由使用它的人员和软件所带来的后果。

因此,如何从A(脚本参数)到B(变量)到C(heredoc)获取命令(可以包含引号,例如带空格的路径,以及可能有多个用分号分隔的命令),而不会造成混乱报价吗?

按照经常引用的FAQ entry中的建议,我使用Bash数组组装了调度程序命令,并且运行良好。但是,尽管我可以这样做:

#/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,但失败。

那我还有什么?

提前谢谢

1 个答案:

答案 0 :(得分:2)

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

#/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