在bash中,我使用dynamic添加的用户名和密码选项来创build一个svn命令。 某些用户的密码中可能带有感叹号,可能会导致以下情况:
svncmd='svn update --username=user --password password\! --non-interactive' $($svncmd)
但是,这扩大了我的感叹号,这不是我想要的。 我错过了什么?
编辑:
啊,我想我知道发生了什么事情。 使用这个命令,我可以像$ svncmd而不是$($ svncmd)那样运行它。 发生了什么事情是bash抱怨bash:at:command not found …当它试图运行“在版本xxxxx”作为一个命令。 哎呀。
由于shellparsing命令行的顺序,将命令存储在一个variables中,然后按预期执行它是非常棘手的。 它分析(并应用和删除)引号和转义,然后replacevariables,然后进行分词和通配符扩展,但不会返回并解释被replace的variables值中的转义和引号。 因此,如果存储在variables中的命令引号或转义,它们将不具有预期的效果。 例如,假设你将命令设置为svncmd='svn update --username=user --password foo * bar --non-interactive' ,那么用户的密码是'foo * bar svncmd='svn update --username=user --password foo * bar --non-interactive' ,然后以$svncmd ,它将把'foo'作为密码,然后获得当前目录中的文件列表,接着是'bar'作为单独的参数。 另一方面,如果你以svncmd='svn update --username=user --password "foo * bar" --non-interactive'forms存储了命令,那么就会把'foo'作为密码,然后“bar”后面的文件列表“…
在bash中处理这个问题的最好方法是将命令存储为数组(其中每个“word”是一个数组元素),然后将其作为"${svncmd[@]}"调用 – [@]使得它将每个元素当作一个命令字,并且双引号可以在数组元素被replace后阻止任何额外的数组元素parsing。因此,您可以像下面这样构build命令:
svncmd=(svn update --username=user) if [ $pwdfromvar ]; then svncmd+=(--password "$userpw") # Double-quotes allow variable substitution, prevent parsing of the substituted value elif [ $defaultpw ]; then svncmd+=(--password 'password!') # Single-quotes prevent the ! from being interpreted else IFS= read -rs -p "Password:" # Raw read without echo echo svncmd+=(--password "$REPLY") fi svncmd+=(--non-interactive) "${svncmd[@]}"