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
argv="su -c \"$RVM_PATH wrapper $config_rvm \\\"$PASSENGER_RVM_BIN $command $options\\\"\" web"
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.
#!/bin/bash
cmd=(echo "foo bar")
"${cmd[@]}"
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