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

时间:2011-04-19 17:20:06

标签: 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

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

工作示例:

notify-finished rsync -avz source/ user@remote:dest/

失败的例子:

notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/

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

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

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

如何让所有参数都能正常工作?

2 个答案:

答案 0 :(得分:25)

"$@" 引号一起使用:

prog="$1"
"$@"
ecode="$?"
echo "$prog exited with $ecode"

这将完全按照收到的方式传递每个参数。如果您不包含引号,则每个元素将根据$IFS分割:

  • "$@""$1" "$2" "$3" ...类似,将每个元素作为单独的参数传递。
  • "$*""$1 $2 $3 ..."类似,将所有连接的元素作为单个参数传递
  • $*$@类似于$1 $2 $3 ...,分解空白处的每个元素,展开所有数据,并将每个结果单词作为单独的元素传递($IFS)。

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

答案 1 :(得分:4)

在变量替换周围加上双引号以防止它们被解析(请注意,这适用于所有变量:$@$1$PROG)。另外:在分配变量名时,不要在变量名之前放置$;使用#进行评论;并且,在最后一行,单引号将阻止变量被替换。

PROG="$1"
shift
# Run program below
"$PROG" "$@"
ECODE=$? # note: this will always be a number, so it doesn't have to be protected with double-quotes
echo -e "Subject: $(hostname): $PROG finished\r\nTo: <$USER>\r\n\r\nExited with $ECODE\r\n' | sendmail "$USER"