变量内的引号将被忽略

时间:2013-07-03 19:39:58

标签: bash

我想从这样的变量中将参数传递给rsync

myopts='-e "ssh -p 1234" -a'
rsync $myopts 192.168.0.1:/a /a

出于某种原因,这不起作用。我甚至发现this webpage说它无效:

### NO NO NO: this passes three strings:
###      (1)  "my
###      (2)  multiword
###      (3)  argument"
MYARG="\"my multiword argument\""
somecommand $MYARG

### THIS IS NOT (!!!!) THE SAME AS ###
command "my multiword argument"

### YOU NEED ###
MYARG="my multiword argument"
command "$MYARG"

不幸的是,它没有说为什么它不起作用。

包含rsync调用的脚本被许多其他脚本使用,因此我只能以兼容的方式更改它。无效的解决方案是使用数组:

myopts=('-a' '-v' '-z') # new way, would work
myopts='-a -v -z'       # old way, breaks
rsync "${myopts[@]}" 192.168.0.1:/a /a

完全忽略变量中的选项。

2 个答案:

答案 0 :(得分:9)

它与Bash拆分参数的方式有关。现在,永远不要将命令和参数放在一个变量中。使用数组代替(并且,停止使用大写的变量名称,它是丑陋和危险的,因为它可能与已定义的变量冲突)。你应该写:

myopts=( -e "ssh -p 1234" )
rsync "${myopts[@]}" 192.168.0.1:/a /a

在这种情况下,rsync将使用以下参数启动:

-e
ssh -p 1234
192.168.0.1:/a
/a

这可能是你想要的。


关于为什么它以这种方式工作:假设

myopts='-e "ssh -p 1234"'

即,myopts是以下字符串:

-e "ssh -p 1234"

不带引号,Bash会看到四个令牌。您可以这样检查:在终端中执行:

$ myopts='-e "ssh -p 1234"'
$ printf 'Token: %s\n' $myopts
Token: -e
Token: "ssh
Token: -p
Token: 1234"

所以当你启动时

rsync $myopts 192.168.0.1:/a /a

然后就像使用这些参数启动rsync

-e
"ssh
-p
1234"
192.168.0.1:/a
/a

您可能不希望:)

现在,变量$myopts 引用,只是一个标记:

-e "ssh -p 1234"

所以如果你启动(观察引号):

rsync "$myopts" 192.168.0.1:/a /a

就像使用以下参数启动rsync

-e "ssh -p 1234"
192.168.0.1:/a
/a

你也不想要。

实际上,解决此问题的最有效方法是使用Bash数组。看:将数组 myopts定义为(在终端中执行):

$ myopts=( -e "ssh -p 1234" )
$ # myopts is an array with two arguments. Check this (observe the quotes):
$ printf "Argument: %s\n" "${myopts[@]}"
Argument: -e
Argument ssh -p 1234
$ # Just for fun, what if we don't quote myopts?
$ printf "Argument: %s\n" ${myopts[@]}
Argument: -e
Argument: "ssh
Argument: -p
Argument 1234"

所以现在,我猜你明白为什么:

rsync "${myopts[@]}" 192.168.0.1:/a /a

就像使用以下参数启动rsync

-e
ssh -p 1234
192.168.0.1:/a
/a

......这可能就是你想要的:)

希望这有帮助!

答案 1 :(得分:2)

在变量扩展之后,唯一的处理是分词和通配符扩展(如果变量在双引号内,这些都不会完成),而不是引用处理。如果希望重做命令行解析的所有步骤,则需要使用eval

eval "rsync $MYOPTS 192.168.0.1:/a /a"