У меня есть скрипт, который получает N параметров. Сначала он их анализирует (извлекает определенное значение X
), затем вызывает другую программу с указанным значением:
function main() {
parse "$@"
run "$@"
}
main "$@"
Я хочу добавить необязательный параметр в начале списка аргументов (параметр для установки версия питона у меня работает). Поэтому я добавил это к функции разбора:
if [ "$1" = '2' ] || [ "$1" = '3' ]; then version=$1 && shift; else version=2; fi
Однако после окончания разбора я застрял, потому что shift
не влияет на функцию запуска. Как я могу сделать это, не проверяя снова значение первого значения (что лишило бы цели использования функции синтаксического анализа)
Объем каждой функции оболочки (а также объем кода верхнего уровня в сценарии) имеет свои собственные позиционные параметры и может только непосредственно получить доступ к его собственному. Самое чистое решение состоит в том, чтобы поместить значения позиционных параметров, которыми Вы интересуетесь в массив. Можно затем читать и также изменить, тот массив в нескольких функциональных объемах.
Например, у Вас мог быть этот код, появляются около начала Вашего сценария:
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 Функциональной вызывающей стороне позиционные параметры.