Expliquez la commande shell: shift $ (($ optind - 1))

30

Je ne suis pas un gars Linux mais coincé dans un script que je dois lire pour mon projet. Alors, quelqu'un peut-il m'aider sur ce que fait cette commande?

shift $(($optind - 1))
Pantalon Gaurav
la source
3
Comme indiqué ci-dessous, OPTIND doit être en majuscules et le «$» à l'intérieur de la parenthèse est facultatif.
DarkHeart

Réponses:

49

shift $((OPTIND-1))(la note OPTINDest en majuscule) se trouve normalement immédiatement après une getopts whileboucle. $OPTINDest le nombre d'options trouvées par getopts.

Comme le mentionne pauljohn32 dans les commentaires, à proprement parler, OPTINDdonne la position du prochain argument de ligne de commande.

Dans le manuel de référence GNU Bash :

getopts optstring name [arguments]

getoptsest utilisé par les scripts shell pour analyser les paramètres positionnels. optstringcontient les caractères d'option à reconnaître; si un caractère est suivi de deux points, l'option devrait avoir un argument, qui devrait être séparé de celui-ci par des espaces. Les deux points (':') et le point d'interrogation ('?') Ne peuvent pas être utilisés comme caractères d'option. Chaque fois qu'elle est invoquée, getoptsplace l'option suivante dans le nom de la variable shell, initialisant namesi elle n'existe pas, et l'index de l'argument suivant à traiter dans la variable OPTIND. OPTINDest initialisé à 1 chaque fois que le shell ou un script shell est appelé. Lorsqu'une option nécessite un argument, getopts place cet argument dans la variable OPTARG. Le shell ne se réinitialise pasOPTIND automatiquement; il doit être réinitialisé manuellement entre plusieurs appels getoptsdans le même appel de shell si un nouvel ensemble de paramètres doit être utilisé.

Lorsque la fin des options est rencontrée, getoptsquitte avec une valeur de retour supérieure à zéro. OPTINDest défini sur l'index du premier argument sans option et le nom est défini sur "?".

getoptsanalyse normalement les paramètres de position, mais si plus d'arguments sont fournis args, les getoptsanalyse à la place.

shift n
supprime n chaînes de la liste des paramètres de position. shift $((OPTIND-1))Supprime ainsi toutes les options qui ont été analysées par getoptsde la liste des paramètres, et donc après ce point, $1se référera au premier argument de non-option passé au script.

Mise à jour

Comme le mentionne mikeserv dans le commentaire, cela shift $((OPTIND-1))peut être dangereux. Pour éviter le fractionnement de mots indésirables, etc., toutes les extensions de paramètres doivent être entre guillemets doubles. Donc, la forme sûre de la commande est

shift "$((OPTIND-1))"

PM 2Ring
la source
Il semble que cela ne fonctionnera correctement que si toutes les options se produisent avant tout argument positionnel restant. Correct?
Steve Jorgensen
@SteveJorgensen: Oui, c'est exact. OTOH, placer des options après des arguments sans option va à l'encontre de la convention sh / bash. Généralement, les premiers arguments qui ne commencent pas par un tiret signifient la fin des options, et tous les arguments suivants qui commencent par un tiret ne sont pas considérés comme des options. Tous les programmes n'adhèrent pas à cette convention, mais cela vous simplifie beaucoup la vie. :)
PM 2Ring
@SteveJorgensen: (suite) Ce sujet est traité brièvement dans Pourquoi certains utilitaires analysent-ils les opérandes avant les options? . Comme le mentionne le commentaire de Gilles à la réponse de Celada, certains programmes (comme find) peuvent sembler autoriser les options après les non-options, mais ils ne le font pas: ils ont des opérandes qui commencent par un tiret.
PM 2Ring
Merci pour ces informations (et la modification) @mosvy C'est assez inhabituel IFS, mais il vaut mieux prévenir que guérir. ;)
PM 2Ring
@roaima if IFS=0123456789, shift $((OPTIND-1))(sans guillemets) se transformera en shift ""lequel sera silencieusement ignoré (in ksh) ou générera une erreur (in bashand dash).
mosvy
8

$((...))calcule juste des trucs. Dans votre cas, il prend la valeur de $optintet soustrait 1.

shiftsupprime les paramètres de position. Dans votre cas, il supprime les optint-1paramètres.

Pour plus d' informations consulter help getopts, help shift, regardez man bashpour « Arithmétique », et en particulier Google pour getopts.

michas
la source