как сдвинуть параметр и выбросить его целиком из args ls?

У меня есть скрипт, который получает N параметров. Сначала он их анализирует (извлекает определенное значение X), затем вызывает другую программу с указанным значением:

function main() {
    parse "$@"
    run "$@"
}
main "$@"

Я хочу добавить необязательный параметр в начале списка аргументов (параметр для установки версия питона у меня работает). Поэтому я добавил это к функции разбора:

if [ "$1" = '2' ] || [ "$1" = '3' ]; then version=$1 && shift; else version=2; fi

Однако после окончания разбора я застрял, потому что shift не влияет на функцию запуска. Как я могу сделать это, не проверяя снова значение первого значения (что лишило бы цели использования функции синтаксического анализа)

3
задан 13 June 2019 в 00:54

1 ответ

Объем каждой функции оболочки (а также объем кода верхнего уровня в сценарии) имеет свои собственные позиционные параметры и может только непосредственно получить доступ к его собственному. Самое чистое решение состоит в том, чтобы поместить значения позиционных параметров, которыми Вы интересуетесь в массив. Можно затем читать и также изменить, тот массив в нескольких функциональных объемах.

Например, у Вас мог быть этот код, появляются около начала Вашего сценария:

declare -a args=("$@")
  • Назовите массив однако, Вам нравится - это нельзя назвать args.
  • Можно даже опустить declare -a, если Вы хотите.
  • Это не должно действительно появляться около начала. Это просто должно работать перед любым кодом это получает доступ args выполнения. Это могло даже появиться ниже определений функций оболочки то использование args. Для ясности я предлагаю поместить его где-нибудь около начала.

Затем можно воздействовать на args массив от нескольких функций. Вы не должны передавать его функциям; они уже смогут получить доступ к нему. Когда код в функции оболочки изменяет содержание args и затем возвраты, код в вызывающей стороне сможет наблюдать изменения.

Позиционные параметры в оболочках стиля Границы, включая Bash, используют индексацию на основе 1. (Это вызвано тем, что $0, который расширяется до названия программы, является технически не позиционным параметром и не изменяется в функциональных объемах.), Но массивы в Bash используют индексацию на основе 0. Так, после args=("$@"), $1 соответствия ${args[0]}, $2 соответствия ${args[1]}, $3 соответствия ${args[2]}, и т.д. $@ все еще соответствия ${args[@]} поскольку Вы ожидали бы.

Я записал им тот путь, закрыл кавычки, для удобочитаемости. Вы будете, конечно, почти всегда хотеть к расширениям двойной кавычки, включающим Ваш args массив, как Вы почти всегда хотели бы к расширениям двойной кавычки, включающим позиционные параметры.

Если Вы решаете пойти с этим подходом, то вместо:

shift

Вы записали бы:

args=("${args[@]:1}")

Если Вы будете плохо знакомы с массивами в Bash, то Вы захотите смотреть на соответствующую часть справочника Bash. Можно также хотеть экспериментировать в интерактивном режиме. Например:

ek@Cord:~$ args=('foo bar' 'baz quux' 'ham spam')
ek@Cord:~$ printf '[%s]\n' "${args[@]}"
[foo bar]
[baz quux]
[ham spam]
ek@Cord:~$ printf '[%s]\n' "${args[@]:1}"
[baz quux]
[ham spam]

Соответствие кода

if [ "$1" = 2 ] || [ "$1" = 3 ]; then
    version="$1"
    shift
else
    version=2
fi

был бы:

if [ "${args[0]}" = 2 ] || [ "${args[0]}" = 3 ]; then
    version="${args[0]}"
    args=("${args[@]:1}")
else
    version=2
fi

Используя массив является синтаксически более громоздким, но также и более гибким.

С другой стороны, так как у Вас, кажется, есть большая часть кода Вашего сценария, организованного в a run функционируйте и его вызываемые так или иначе, Вы могли бы рассмотреть альтернативу для парсинга любых специальных параметров командной строки перед вызовом run, за пределами любой функции оболочки и затем вызова run "$@" поскольку Вы уже делаете.

Существуют языки программирования, связанные культуры которых имеют сильную этику помещения почти всего в маленький (выход), автономные функции. Bash не является таким языком, и ограниченными способами возвратить сложные данные из функции оболочки является одна из причин. Вы не должны бояться записать функции оболочки, и необходимо даже быть готовы записать огромное количество крошечных функций оболочки. Но я не думаю, что Вы должны быть взволнованы, оказывается ли, что лучшая форма для Вашего сценария - что-то еще.

Для дополнительных материалов для чтения и некоторых альтернатив включая странный подход, где Вы получаете вывод замены процесса, см. ответ Gilles Функциональной вызывающей стороне позиционные параметры.

1
ответ дан 13 June 2019 в 00:54

Другие вопросы по тегам:

Похожие вопросы: