bash 如何传递包含引号/空格的脚本参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5720194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I pass on script arguments that contain quotes/spaces?
提问by axon
I'm trying to write a script notify-finishthat can be prepended to any command. When done, it will run the command given by the arguments following, then email the user when the command is complete. Here's what I have:
我正在尝试编写一个notify-finish可以添加到任何命令的脚本。完成后,它将运行由以下参数给出的命令,然后在命令完成时向用户发送电子邮件。这是我所拥有的:
PROG=
# 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
This works most of the time, but when arguments contain spaces, the quoting is stripped off.
这在大多数情况下都有效,但是当参数包含空格时,引用将被删除。
Working example:
工作示例:
notify-finished rsync -avz source/ user@remote:dest/
Failing example:
失败的例子:
notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/
In the second case, $@is expanded out to rsync -avz -e ssh -c blowfish source user@remote:dest/, missing the single quotes. It does not work with double-quotes either, nor with $*.
在第二种情况下,$@扩展为rsync -avz -e ssh -c blowfish source user@remote:dest/,缺少单引号。它不适用于双引号,也不适用于$*.
After reading other posts I tried putting the command in an array, but I get the exact same issue:
阅读其他帖子后,我尝试将命令放入数组中,但遇到了完全相同的问题:
CMD=(notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/)
${CMD[@]}
How do I make this work for all arguments?
我如何使所有参数都适用?
回答by Micha? ?rajer
Use "$@"withquotes:
"$@"与引号一起使用:
prog=""
"$@"
ecode="$?"
echo "$prog exited with $ecode"
This will pass each argument exactly as it was received. If you don't include the quotes, each element will be split according to $IFS:
这将完全按照收到的方式传递每个参数。如果不包含引号,每个元素将根据以下内容拆分$IFS:
"$@"is like"$1" "$2" "$3" ..., passing each element as a separate argument."$*"is like"$1 $2 $3 ...", passing all elements concatenated as a single argument$*and$@is like$1 $2 $3 ..., breaking up each element on whitespace, expanding all globs, and passing each resulting word as a separate element ($IFS).
"$@"就像"$1" "$2" "$3" ...,将每个元素作为单独的参数传递。"$*"就像"$1 $2 $3 ...",将所有元素作为单个参数连接在一起$*和$@像$1 $2 $3 ...,分手每个元件上的空白,扩大所有水珠,并通过每个得到字作为一个单独的元件($IFS)。
The same is true for arrays, such as "${array[@]}"and "${array[*]}"
数组也是如此,例如"${array[@]}"和"${array[*]}"
回答by Gordon Davisson
Put double-quotes around your variable substitutions to keep them from being parsed (note that this applies to all variables: $@, $1, and $PROG). Also: don't put a $ before a variable name when assigning to it; use #for comments; and, on the last line, the single-quotes will prevent variables from being substituted at all.
在您的变量替换周围加上双引号以防止它们被解析(请注意,这适用于所有变量:$@、$1、 和$PROG)。另外:分配给变量名时不要在变量名前加上 $;使用#征求意见; 并且,在最后一行,单引号将完全阻止变量被替换。
PROG=""
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"

