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

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

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

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

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

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

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

решение1

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

Например, вы можете разместить этот код в начале вашего скрипта:

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

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

Позиционные параметры в оболочках в стиле Bourne, включая 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

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

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

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

Для дальнейшего чтения и некоторых альтернатив, включая странный подход, при котором вы получаете выходные данные подстановки процесса, см.Ответ ЖилякПозиционные параметры вызывающей функции.

Связанный контент