У меня есть скрипт-обертка, который выполняет некоторую работу, а затем передает исходные параметры другому инструменту:
#!/bin/bash
# ...
other_tool -a -b "$@"
Это работает нормально, если «другой инструмент» не запускается в подоболочке:
#!/bin/bash
# ...
bash -c "other_tool -a -b $@"
Если я назову мой скрипт-обертку так:
wrapper.sh -x "blah blup"
затем только первый оригинальный аргумент (-x) передается «other_tool». На самом деле я не создаю подоболочку, а передаю исходные аргументы оболочке на телефоне Android, что не должно иметь никакого значения:
#!/bin/bash
# ...
adb sh -c "other_tool -a -b $@"
Ни одно из решений не работает хорошо. Просто передайте x / \ \ "b \" / aaaaa / \ 'xxx \ yyyy \' / zz \ "offf \" в качестве параметра, и они не пройдут.
Вот простая оболочка, которая обрабатывает каждый случай. Обратите внимание, как он избегает каждого аргумента дважды.
источник
Изменить
$@
на$*
. Я сделал небольшой локальный тест, и он работает в моем случае.Сохранение как
test.sh
и выполнение его даетМежду ними
$*
и$@
, как вы можете видеть, есть небольшая разница . Смотрите, например, http://ss64.com/bash/syntax-parameters.htmlДля последующего вопроса в комментариях: вам нужно экранировать, например, пробел «дважды», чтобы передать строку с разделителем в качестве объединенного аргумента, например, с
test.sh
изменением вwc
оболочку:Это работает:
но:
источник
wrapper.sh -x "blah blup"
тогда подоболочка получает ТРИ параметра (-x, бла, блеф) вместо ДВУХ (-x, «бла блюп»)"Blah\ blup"
. Попробуйте и посмотрите, работает ли это.Это терпит неудачу, потому что вы приводите массив (позиционные параметры) в строку.
"$@"
магический, потому что он дает вам каждый отдельный параметр в виде строки в правильных кавычках. Добавление дополнительного текста разрушает магию:"blah $@"
это всего лишь одна строка.Это может приблизить вас:
Конечно, любой параметр, содержащий одну кавычку, вызовет проблемы.
источник
Хорошо, больше объяснений:
источник
Я пробовал много разных решений, хороший ресурс, включая справочную информацию и альтернативы, например, BashFAQ / 096 на вики Грега (он же GreyCat) . В целом я обнаружил, что следующие два являются наиболее читаемыми (из рабочих):
Начиная с Bash 4.4 (насколько я мог судить из новостей ), можно использовать расширение параметра
@Q
следующим образом:Обратите внимание, что я использую
$*
здесь вместо того,$@
потому что вы хотите"other_tool -a -b ${*@Q}"
быть одной единственной строкой вместо одной строки на переданный аргумент.Если вы хотите сделать то же самое с переменной массива bash, вам потребуется синтаксис
${ARRAY[*]@Q}
(в кавычках).Если у вас нет Bash 4.4 или более поздней версии или вы не уверены, это мое предпочтительное решение:
Обратите внимание, что здесь вам нужно использовать
"$@"
вместо$@
или"$*"
или$*
потому, что вы не хотите разделять слова в аргументах, поэтому варианты без кавычек не могут быть использованы, и вы хотите, чтобы количество аргументов было сохранено, поэтому"$*"
не может быть использовано, так как оно объединяет все аргументы в одну строку. Затем функция возвращает все аргументы в одной строке.Если вас не волнует дополнительное пространство перед первым аргументом, вы можете изменить
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 '$"'\''({:})'
→'$"'\''({:})'
или\$\"\'\(\{:\}\)
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) -релизом.)
источник
источник