Как изменить аргумент командной строки в Bash?

97

Есть ли способ изменить аргументы командной строки в сценарии Bash? Например, сценарий Bash вызывается следующим образом:

./foo arg1 arg2  

Есть ли способ изменить значение arg1 в скрипте? Что-то типа:

$1="chintz"
Шрирам
источник

Ответы:

153

Вам нужно сбросить все аргументы. Чтобы изменить, например $3:

$ set -- "${@:1:2}" "new" "${@:4}"

Обычно вы устанавливаете для всех аргументов их текущие значения, кроме одного (-ых), который вы хотите изменить. set --также указан в POSIX 7 .

"${@:1:2}"Обозначения расширяется до двух (следовательно, 2в обозначениях) позиционные аргументы , начиная от смещения 1(то есть $1). В "$1" "$2"данном случае это сокращение для , но оно гораздо более полезно, если вы хотите заменить, например "${17}".

Thkala
источник
1
Итак, чтобы поменять 3 доллара, я должен также поменять 1 и 2 доллара, не так ли? И поменять их на что? Что значит "сбросить"?
Шрирам
Спасибо за фокус! Мне было трудно использовать это для имен файлов со встроенными пробелами. Для всех , кто может запустить в эту проблему, попробуйте положить evalна передней линии в этом .
cxw
2
Это нормально, если вы знаете положение параметра, который хотите изменить. Что, если вы на самом деле этого не знаете и вам нужно его динамически изменять? Я пробовал использовать $ set - "$ {: 1: $ pivot}", но он не принимает там переменную.
Даниэле Сегато
1
Как я могу сделать то же самое изнутри функции? Ваше решение, похоже, не работает при вызове изнутри функции.
Hashken
3
Вы не можете изменить позиционные параметры скрипта изнутри функции - собственные аргументы функции скрывают их. Однако вы можете хранить их в массиве и работать с ним.
thkala
23

Оптимизируя читаемость и удобство обслуживания, вам может быть лучше назначить $1и $2более значимые переменные (я не знаю, input_filename = $1и output_filename = $2или что-то в этом роде), а затем перезаписать одну из этих переменных ( input_filename = 'chintz'), оставив входные данные для скрипта без изменений, если это нужен в другом месте.

Johnsyweb
источник
Мне нужен был подход, в котором я мог бы изменить сам один из входных аргументов. Мне нужно было это сделать, так как я хотел вернуть значение из скрипта. Ответ, предложенный thkala, сработал. Спасибо за ответ!!!
Шрирам,
3
@Johnsyweb Согласен. Для удобства чтения ваш метод лучше.
Dss
1
«Вам будет лучше» всегда зависит от варианта использования, который не предусмотрен.
Его
2
@Scott на 7 лет старше и опытнее меня, когда я писал этот ответ, я склонен согласиться с вами.
Johnsyweb
Пример, когда это не сработает (кроме использования чего-то вроде $ FIRST_PARAMETER): использование и значение параметра зависят от фактического значения.
Игорь Стоппа
0

Я знаю, что это старый, но я нашел ответ thkala очень полезным, поэтому я использовал эту идею и немного расширил ее, чтобы позволить мне добавить значения по умолчанию для любого аргумента, который не был определен, например:


    # set defaults for the passed arguments (if any) if not defined.
    #
    arg1=${1:-"default-for-arg-1"}
    arg2=${2:-"default-for-arg-2"}
    set -- "${arg1}" "${arg2}"
    unset arg1 arg2

Надеюсь, это кому-то пригодится.

mr_thinkit
источник