首页 > 解决方案 > 如何将整个命令存储在 bash 变量中并以有限的分词方式逐字执行它们?

问题描述

我有很多行如下所示,其中前缀始终相同,实际执行的命令不同。

ssh -F "${SSH_CFG}" "${SSH_DST}" "[...]"
ssh -F "${SSH_CFG}" "${SSH_DST}" "[...]"
ssh -F "${SSH_CFG}" "${SSH_DST}" "[...]"

为了不需要重复自己,我想让整个前缀也成为一个变量,如下例所示:

SSH_CMD="ssh -F ""${SSH_CFG}"" ""${SSH_DST}"""

${SSH_CMD} "[...]"
${SSH_CMD} "[...]"
${SSH_CMD} "[...]"

只要空格不用作路径或选项的一部分,它就可以工作,因为据我了解,上面使用的前缀会受到 shell 的分词。当然,出于各种原因,我有一些带有空格的选项,这些选项需要按原样转发,作为一个论点。在上面的示例中情况并非如此,并且整个命令都失败了。OTOH,引用前缀也是错误的,因为在这种情况下,一个带有参数的命令将被视为一个文件并且找不到。所以下面的例子不起作用:

SSH_CMD="ssh -F ""${SSH_CFG}"" ""${SSH_DST}"""

"${SSH_CMD}" "[...]"
"${SSH_CMD}" "[...]"
"${SSH_CMD}" "[...]"

我想要的是一个像上面这样的变量,SSH_CMD其中包含一个已经预先引用的字符串来处理空格等,并且该字符串按原样用作前缀。虽然,在那种情况下,我仍然需要 shell 使用空格进行某种程度的分词来区分命令和所有单独的参数,但是在这些参数中,分词不能发生以保持路径和带有空格的选项正确。我找不到解决后者的方法:无论我尝试什么都无法在分词中幸存下来,或者像"或被'添加到路径和选项中的字符,很可能也是错误分词的结果。

SSH_CMD="ssh -F ""${SSH_CFG}"" ""${SSH_DST}"""

${SSH_CMD} "[...]"
${SSH_CMD} "[...]"
${SSH_CMD} "[...]"

SSH_CMD="ssh -F ""${SSH_CFG}"" ""${SSH_DST}"""

ssh -F "${SSH_CFG}" "${SSH_DST}" "[...]"
ssh -F "${SSH_CFG}" "${SSH_DST}" "[...]"
ssh -F "${SSH_CFG}" "${SSH_DST}" "[...]"

那么,有没有办法让上面的例子完全起作用?

谢谢!

标签: bashshellscriptingquoting

解决方案


定义一个函数,而不是一个变量。

ssh_cmd () {
    ssh -F "$SSH_CFG" "$SSH_DST" "$@"
}


ssh_cmd "[...]"
ssh_cmd "[...]"
ssh_cmd "[...]"

函数的主体不需要超出您通常使用的额外引用,并"$@"确保您的参数ssh_cmd在调用中保留为不同的参数ssh


推荐阅读