Bash嵌套引号和eval

时间:2012-03-01 03:49:07

标签: bash nested eval quotes

我在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

4 个答案:

答案 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)

Use an array instead.

#!/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不是邪恶的-只是被误解了:)