如何传递包含引号/空格的脚本参数?

axo*_*xon 23 bash quoting

我正在尝试编写一个notify-finish可以添加到任何命令之前的脚本.完成后,它将运行以下参数给出的命令,然后在命令完成时通过电子邮件发送给用户.这就是我所拥有的:

PROG=$1
# Run command given by arguments
$@
ECODE=$?
echo -e "Subject: `hostname`: $PROG finished\r\nTo: <$USER>\r\n\r\nExited with $ECODE\r\n" | sendmail $USER
Run Code Online (Sandbox Code Playgroud)

这在大多数情况下都有效,但是当参数包含空格时,引用会被删除.

工作范例:

notify-finished rsync -avz source/ user@remote:dest/
Run Code Online (Sandbox Code Playgroud)

失败的例子:

notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,$@扩展到rsync -avz -e ssh -c blowfish source user@remote:dest/,缺少单引号.它也不适用于双引号,也不适用于$*.

在阅读其他帖子之后,我尝试将命令放在一个数组中,但是我得到了完全相同的问题:

CMD=(notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/)
${CMD[@]}
Run Code Online (Sandbox Code Playgroud)

我如何使这项工作适用于所有论点?

Mic*_*jer 25

"$@" 与引号一起使用:

prog="$1"
"$@"
ecode="$?"
echo "$prog exited with $ecode"
Run Code Online (Sandbox Code Playgroud)

这将完全按照收到的方式传递每个参数.如果不包括引号,则每个元素将根据以下内容进行拆分$IFS:

  • "$@"就像"$1" "$2" "$3" ...把每个元素作为一个单独的参数传递一样.
  • "$*"就像"$1 $2 $3 ..."传递所有连接成一个参数的元素一样
  • $*并且$@就像是$1 $2 $3 ...,分解空白上的每个元素,扩展所有的全局,并将每个结果单词作为单独的元素传递($IFS).

对于数组也是如此,例如"${array[@]}"和"${array[*]}"

  • 这是特别针对双引号内的`$ @`的特殊行为. (4认同)
  • @axon:如果要将参数存储在变量中,可以使用数组变量:`ARGS =("$ @"); "$ PROG""$ {ARGS [@]}"` (4认同)