Bash nested quotes and eval

拈花ヽ惹草 提交于 2019-11-30 01:47:47

问题


I'm having difficulty nested quotes within a bash script

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

回答1:


argv="su -c \"$RVM_PATH wrapper $config_rvm \\\"$PASSENGER_RVM_BIN $command $options\\\"\" web"



回答2:


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.




回答3:


Use an array instead.

#!/bin/bash
cmd=(echo "foo bar")
"${cmd[@]}"



回答4:


Generic solution for eval with correctly quoted arguments

The following function uses the shell's own quoting mechanism to that I don't have to worry about how to correctly quote things:

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 \.

$ 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 seemingly correct quoting:

% eval "$(echo "${cmd[@]}")"
User gave: Trying to hack you
Thu Sep 27 20:41:31 +07 2018

Note you were hacked. date was executed rather than being printed literally.

Instead with token_quote():

% eval "$(token_quote "${cmd[@]}")"
User gave: Trying to hack you; date
%

eval isn't evil - it's just misunderstood :)



来源:https://stackoverflow.com/questions/9510362/bash-nested-quotes-and-eval

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!