bash:在函数中构造命令行部分,被解释为单独的参数(包括引号)

bash: construct command line parts in function, to be interpreted as separate arguments (including quotes)

我想执行这样的 shell 命令:

convert input.png -pointsize 40 -font "$HOME/Library/Fonts/Droid Sans.ttf" \
 -background black -fill red -stroke blue label:"Foo Bar" \
 -gravity center -composite output.png

但它是脚本的一部分,并且某些元素是动态的,我从函数中获取这些元素。基本上我正在尝试这样的事情:

function GetTextCommands {
  echo "-pointsize  -font \"$HOME/Library/Fonts/.ttf\" \
   -background black -fill red -stroke blue label:\"\" \
   -gravity center -composite"
}

bla=$(GetTextCommands "Droid Sans" 40 "Foo Bar")
convert input.png $bla output.png

然而,我总是遇到与报价相关的问题。要么它不识别 Sans.ttf 部分,认为这是一个不同的论点。或者,如果我在 convert 命令中将 $bla 变量用引号引起来,它会将整个事物解释为一个参数(当然,这将被视为无效)。

请注意,如果我在 convert 命令之前放置一个 echo 来预览我的命令行的实际外观,它看起来就像我想要的那样。但我意识到当整行被回显时,一些引用可能会消失。

解决这个问题的正确方法是什么?

而不是尝试生成要执行的字符串(这需要传递给 eval,也许您正在寻找的解决方案只是调用 eval convert input.png "$bla" output.png,但存在陷阱所以我不推荐它),只需在你的函数中调用:

function ExecTextCommands {
  convert input.png "" -pointsize "" -font "$HOME/Library/Fonts/.ttf" \
   -background black -fill red -stroke blue label:"" \
   -gravity center -composite output.png
}

ExecTextCommands "Droid Sans" 40 "Foo Bar"

一个正确的方法是让您的函数填充一个包含参数的全局数组:

getTextCommands () {
    args=(
      -pointsize ""
      -font "$HOME/Library/Fonts/.ttf"
      -background black
      -fill red
      -stroke blue
      "label:"
      -gravity center
      -composite
    )
}

getTextCommands "Droid Sans" 40 "Foo Bar"
convert input.png "${args[@]}" output.png

一个缺点是使用 getTextCommands 需要您知道它设置的变量的名称。