我在bash脚本中嵌套引号有困难
argv="su -c '$RVM_PATH wrapper $config_rvm \'$PASSENGER_RVM_BIN $command $options\'' web"
eval $argv
以上让我
eval: line 162: unexpected EOF while looking for matching `''
eval: line 163: syntax error: unexpected end of file
答案 0 :(得分:12)
argv="su -c \"$RVM_PATH wrapper $config_rvm \\\"$PASSENGER_RVM_BIN $command $options\\\"\" web"
答案 1 :(得分:9)
那是因为\'
在单引号字符串中没有任何特殊含义;它意味着“反斜杠,然后是字符串结尾”。
一种选择是使用$'...'
代替'...
';这将让你使用反斜杠转义。它看起来像这样:
argv="su -c $'$RVM_PATH wrapper $config_rvm \'$PASSENGER_RVM_BIN $command $options\'' web"
缺点是,如果$RVM_PATH
,$config_rvm
或任何其他变量有可能包含反斜杠,那么它也可能被解释为引入反斜杠转义。
答案 2 :(得分:7)
#!/bin/bash
cmd=(echo "foo bar")
"${cmd[@]}"
答案 3 :(得分:0)
eval
的通用解决方案以下功能使用了外壳程序自身的报价机制,我不必担心如何正确报价:
function token_quote {
local quoted=()
for token; do
quoted+=( "$(printf '%q' "$token")" )
done
printf '%s\n' "${quoted[*]}"
}
用法示例:
$ token_quote token 'single token' token
token single\ token token
上面,请注意single token
的空格引用为\
。
$ set $(token_quote token 'single token' token)
$ eval printf '%s\\n' "$@"
token
single token
token
$
这表明令牌确实分开存放。
提供一些不受信任的用户输入:
% input="Trying to hack you; date"
构造一个命令进行评估:
% cmd=(echo "User gave:" "$input")
用正确的报价貌似对它进行评估:
% eval "$(echo "${cmd[@]}")"
User gave: Trying to hack you
Thu Sep 27 20:41:31 +07 2018
请注意,您被黑了。 date
被执行,而不是照字面意思打印。
用token_quote()
代替:
% eval "$(token_quote "${cmd[@]}")"
User gave: Trying to hack you; date
%
eval
不是邪恶的-只是被误解了:)