Универсальное многоразовое решение
Хотя понимание того, как правильно цитировать вещи, важно для простоты использования и предотвращения ошибок, я предпочитаю использовать функцию:
Следующие элементы оставляют пробелы варгументы, заключив в кавычки каждый элемент массива:
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
не зло - это просто неправильно понято:)