Bash 嵌套引号和 eval
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9510362/
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
Bash nested quotes and eval
提问by Zeophlite
I'm having difficulty nested quotes within a bash script
我在 bash 脚本中难以嵌套引号
argv="su -c '$RVM_PATH wrapper $config_rvm \'$PASSENGER_RVM_BIN $command $options\'' web"
eval $argv
The above got me
以上让我
eval: line 162: unexpected EOF while looking for matching `''
eval: line 163: syntax error: unexpected end of file
回答by Zeophlite
argv="su -c \"$RVM_PATH wrapper $config_rvm \\"$PASSENGER_RVM_BIN $command $options\\"\" web"
回答by ruakh
That's because \'doesn't have any special meaning within a single-quoted string; it means simply "backslash, followed by end-of-string".
那是因为\'在单引号字符串中没有任何特殊含义;它的意思只是“反斜杠,后跟字符串结尾”。
One option is to use $'...'instead of '...'; that will let you use backslash-escapes. It would look like this:
一种选择是使用$'...'而不是'...'; 这将让您使用反斜杠转义。它看起来像这样:
argv="su -c $'$RVM_PATH wrapper $config_rvm \'$PASSENGER_RVM_BIN $command $options\'' web"
The downside is that if there's any chance that $RVM_PATH, $config_rvm, or any of the other variables could include a backslash, then it too could be interpreted as introducing a backslash-escape.
缺点是,如果有任何机会$RVM_PATH,$config_rvm或任何其他变量可以包括一个反斜杠,那么它也可以解释为引入一个反斜杠转义。
回答by Ignacio Vazquez-Abrams
回答by Tom Hale
Generic solution for evalwith correctly quoted arguments
eval正确引用参数的通用解决方案
The following function uses the shell's own quoting mechanism to that I don't have to worry about how to correctly quote things:
以下函数使用 shell 自己的引用机制,我不必担心如何正确引用事物:
function token_quote {
local quoted=()
for token; do
quoted+=( "$(printf '%q' "$token")" )
done
printf '%s\n' "${quoted[*]}"
}
Example usage:
用法示例:
$ token_quote token 'single token' token
token single\ token token
Above, note the single token's space is quoted as \.
上面,请注意single token的空间被引用为\。
$ set $(token_quote token 'single token' token)
$ eval printf '%s\n' "$@"
token
single token
token
$
This shows that the tokens are indeed kept separate.
这表明令牌确实是分开的。
Given some untrusted user input:
鉴于一些不受信任的用户输入:
% input="Trying to hack you; date"
Construct a command to eval:
构造一个命令来评估:
% cmd=(echo "User gave:" "$input")
Eval it, with seeminglycorrect quoting:
评估它,看似正确的引用:
% eval "$(echo "${cmd[@]}")"
User gave: Trying to hack you
Thu Sep 27 20:41:31 +07 2018
Note you were hacked. datewas executed rather than being printed literally.
注意你被黑了。date被执行而不是按字面打印。
Instead with token_quote():
取而代之的是token_quote():
% eval "$(token_quote "${cmd[@]}")"
User gave: Trying to hack you; date
%
evalisn't evil - it's just misunderstood :)
eval不是邪恶的-只是被误解了:)

