Я пробовал много разных решений, хороший ресурс, включая справочную информацию и альтернативы, например, BashFAQ / 096 на вики Грега (он же GreyCat) . В целом я обнаружил, что следующие два являются наиболее читаемыми (из рабочих):
Начиная с Bash 4.4 (насколько я мог судить из новостей ), можно использовать расширение параметра @Q
следующим образом:
adb sh -c "other_tool -a -b ${*@Q}"
Обратите внимание, что я использую $*
здесь вместо того, $@
потому что вы хотите "other_tool -a -b ${*@Q}"
быть одной единственной строкой вместо одной строки на переданный аргумент.
Если вы хотите сделать то же самое с переменной массива bash, вам потребуется синтаксис ${ARRAY[*]@Q}
(в кавычках).
Если у вас нет Bash 4.4 или более поздней версии или вы не уверены, это мое предпочтительное решение:
function escapeBashArgs() {
local arg separator=""
for arg
do
printf "%s%q" "$separator" "$arg"
separator=" "
done
}
adb sh -c "other_tool -a -b $(escapeBashArgs "$@")"
Обратите внимание, что здесь вам нужно использовать "$@"
вместо $@
или "$*"
или $*
потому, что вы не хотите разделять слова в аргументах, поэтому варианты без кавычек не могут быть использованы, и вы хотите, чтобы количество аргументов было сохранено, поэтому "$*"
не может быть использовано, так как оно объединяет все аргументы в одну строку. Затем функция возвращает все аргументы в одной строке.
Если вас не волнует дополнительное пространство перед первым аргументом, вы можете изменить printf
строку формата на " %q"
и удалить separator
переменную. Или вы можете использовать однострочник от Гордона Дэвиссона .
Это решение работает во всех случаях, которые я мог придумать, особенно:
- Нет аргументов:
escapeBashArgs
→ ничего
- Пустые аргументы:
escapeBashArgs "" ""
→'' ''
- Аргументы только с пробелами:
escapeBashArgs " " " "
→ ' ' ' '
или \ \ \ \ \
( последний пробел используется этим рендерером сайтов )
- Аргументы со специальным интервалом и символами новой строки:
escapeBashArgs "a b" c\ d "arg with
newline"
→ 'a b' 'c d' $'arg with\nnewline'
или a\ \ \ \ \ \ b c\ d $'arg with\nnewline'
( символ новой строки находится между with
и newline
, в других позициях это из-за переноса строк на этом сайте )
- Аргументы со специальными символами:
escapeBashArgs '$"'\''({:})'
→ '$"'\''({:})'
или\$\"\'\(\{:\}\)
- Пример ответа от jcayzacs :
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→ 'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
илиx/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(Протестировано с GNU bash 5.0.3 (1) -релизом.)