Lors de l'exécution d'un script shell, est-il possible de passer des paramètres positionnels spécifiques sans avoir à les entrer tous dans l'ordre?

13

Par exemple, si j'ai un script ./foo qui prend 10 paramètres et que je veux seulement passer le 8ème paramètre. La seule façon dont je sais comment faire actuellement est:

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

Existe-t-il un moyen plus facile / meilleur?

Kerry Randolph
la source
1
C'est pourquoi les programmes utilisent généralement des options plutôt que des paramètres positionnels si vous avez beaucoup de paramètres.
Barmar

Réponses:

4

Une autre façon de procéder consiste à nommer le paramètre que vous souhaitez déclarer, puis à le faire:

{   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

PRODUCTION

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

Dans l'exemple ci-dessus, la variable d'environnement explicitement déclarée est préférée à l'argument de ligne de commande, mais l'argument de ligne de commande est utilisé lorsque la variable d'environnement est vide ou non définie. Lorsque la 8e positionnelle et la variable d'environnement $eightsont vides ou non définies, la valeur par défaut à some_default est affectée $eight. Dans les deux cas, le :peut être supprimé des instructions :-or :=si vide doit être une valeur acceptable.

La variable $eightaurait également pu être définie comme:

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

... et la ligne précédente a été entièrement omise, mais je voulais démontrer que déclarer une variable de cette manière entraîne une valeur persistante, et je l'ai donc fait en deux commandes. Dans les deux cas, $eightla valeur finale de l'expansion du paramètre composé est définie.

getopts- pour les scripts robustes - est souvent le meilleur moyen de gérer les options de commande . Les paramètres de position, en revanche, sont presque toujours le moyen le plus simple de gérer de manière robuste les opérandes dans un script.

Par exemple:

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

PRODUCTION

$eight = file008

Là, nous ne voyons que le huitième opérande, mais il y en a 101 globulés dans mon répertoire de test.

mikeserv
la source
18

En supposant que vous pouvez modifier le script, vous devez envisager d'utiliser des paramètres facultatifs (options) au lieu des paramètres requis (arguments).

Si vous avez chacun des 7 sept premiers paramètres comme options et que vous les définissez par défaut sur la chaîne vide, vous pouvez simplement faire:

./foo bar

Si vous utilisez un shell compatible POSIX, vous pouvez utiliser l' getoptsutilitaire ou le programme getopt. bash- comme la plupart des coquilles - offre en getoptstant que intégré. Dans les deux cas, c'est plus facile que de lancer votre propre analyseur de ligne de commande.

À moins que vous n'implémentiez quelque chose comme les derniers arguments X sans option, les valeurs des derniers arguments Y et des arguments d'option XY doivent fournir des chaînes d'options avant chacune des 7 chaînes (maintenant vides) si vous souhaitez définir l'une d'entre elles. Ce n'est cependant pas une pratique courante, normalement une option est toujours une option et un argument un argument, et l'ordre de l'option "insertion" est libre.

Anthon
la source
5
+1pour getopt(s). Les paramètres de position sont une période triste et doivent être évités.
HalosGhost