Bash вложенные цитаты и Eval - PullRequest
12 голосов
/ 01 марта 2012

У меня возникли трудности с вложенными кавычками в 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 ]

12 голосов
/ 01 марта 2012
argv="su -c \"$RVM_PATH wrapper $config_rvm \\\"$PASSENGER_RVM_BIN $command $options\\\"\" web"
9 голосов
/ 01 марта 2012

Это потому, что \' не имеет никакого особого значения в строке в одинарных кавычках;это означает просто «обратную косую черту с последующим концом строки».

Один из вариантов - использовать $'...' вместо '... ';это позволит вам использовать обратную косую черту.Это выглядело бы так:

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

Недостатком является то, что если есть вероятность, что $RVM_PATH, $config_rvm или какая-либо другая переменная может включать обратную косую черту, то это тоже можно интерпретировать каквводя обратную косую черту.

7 голосов
/ 01 марта 2012

Используйте вместо этого массив.

#!/bin/bash
cmd=(echo "foo bar")
"${cmd[@]}"
0 голосов
/ 29 сентября 2018

Общее решение для 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"

Создайте команду для eval:

% 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 не зло - это просто неправильно понято:)

...