Можно ли при запуске сценария оболочки передавать определенные позиционные параметры, не вводя их все по порядку?

13

Например, если у меня есть скрипт ./foo, который принимает 10 параметров, и я хочу передать только 8-й параметр. В настоящее время я знаю, как это сделать:

./foo '' '' '' '' '' '' '' 'bar'

Есть ли более простой / лучший способ?

Керри Рэндольф
источник
1
Вот почему программы обычно используют параметры, а не позиционные параметры, если у вас много параметров.
Бармар

Ответы:

4

Другой способ сделать это - назвать параметр, который вы хотите объявить, и затем сделать это:

{   cat >./foo 
    chmod +x ./foo
    eight=declared ./foo
    eight=declared_and_preferred \
        ./foo 1 2 3 4 5 6 7 8
    ./foo 1 2 3 4 5 6 7 8
    ./foo
} <<\SCRIPT
#!/usr/bin/sh
: ${eight:=${8:-some_default}}
printf '$eight = %s\n' "$eight"
#END
SCRIPT

ВЫХОД

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default

В приведенном выше примере явно объявленная переменная среды предпочтительнее аргумента командной строки, но аргумент командной строки используется, когда переменная среды пуста или не установлена. Когда и восьмые позиционные и переменная окружения $eightявляются пустыми или сбросить значение по умолчанию some_default присваиваются $eight. В любом случае, :можно удалить из операторов :-or, :=если пустое значение должно быть приемлемым.

Переменная $eightмогла также быть установлена ​​как:

printf '$eight = %s\n' "${eight:=${8:-some_default}}"

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

getopts- для надежных сценариев - часто это лучший способ обработки параметров команды . Позиционные параметры, с другой стороны, почти всегда являются наиболее простым средством надежной обработки операндов в скрипте.

Например:

touch file$(seq -ws\ file 100)
./foo *

ВЫХОД

$eight = file008

Там мы видим только восьмой операнд, но 101 из них выведен из моего тестового каталога.

mikeserv
источник
18

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

Если у вас есть каждый из первых 7 семи параметров в качестве параметров, и для них по умолчанию задана пустая строка, вы можете просто сделать:

./foo bar

Если вы используете POSIX-совместимую оболочку, вы можете использовать getoptsутилиту или программу getopt. bash- как и большинство снарядов - предлагает getoptsкак встроенный. В любом случае это проще, чем использовать собственный анализатор командной строки.

Если вы не реализуете что-то наподобие последних X неопциональных аргументов, это значения для последних Y-аргументов и XY-аргументов параметров, вы должны предоставить строки параметров перед каждой из 7 (теперь пустых) строк, если вы хотите установить любой из них. Это, однако, не является обычной практикой, обычно опция всегда является опцией, а аргумент аргументом, и порядок опции «вставка» свободен.

Энтон
источник
5
+1для getopt(s). Позиционные параметры - печальное время, и их следует избегать.
HalosGhost