Pourquoi les espaces entre les options et les paramètres peuvent-ils être omis?

16

Par exemple:

xargs -n 1

est le même que

xargs -n1

Mais si vous regardez la page de manuel , l'option est répertoriée comme -n max-args, ce qui signifie que l'espace est censé être préservé. Il n'y a rien sur la forme abrégée -n max-args .

Cela se produit également avec de nombreux autres utilitaires Linux.

Comment cela s'appelle-t-il sous Linux? Tous les utilitaires prennent-ils en charge le formulaire abrégé (mais ne le documentent jamais dans la page de manuel)?

J.Joe
la source
1
12.1.2.a fait partie de l'histoire; Je jure qu'il y a déjà une bonne question à ce sujet mais je ne l'ai pas encore trouvée.
2
@drewbenn l'autre question à laquelle vous pensez pourrait être la mienne: unix.stackexchange.com/q/188046/41515

Réponses:

12

Lorsque vous écrivez le bit d'analyse de ligne de commande de votre code, vous spécifiez quelles options acceptent les arguments et lesquelles ne le font pas. Par exemple, dans un script shell acceptant une -hoption (pour l'aide par exemple) et une -aoption qui devrait prendre un argument, vous faites

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

Le a:hbit dit "je m'attends à analyser deux options, -aet -h, et -adevrait prendre un argument" (c'est la :suite aqui indique à l'analyseur qui -aprend un argument).

Par conséquent, il n'y a jamais d'ambiguïté quant à la fin d'une option, au début de sa valeur et au début d'une autre après.

L'exécuter:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

C'est pourquoi la plupart du temps, vous ne devez pas écrire votre propre analyseur de ligne de commande pour analyser les options.

Il n'y a qu'un seul cas dans cet exemple qui est délicat. L'analyse se termine généralement à la première non-option, donc lorsque vous avez des éléments sur la ligne de commande qui ressemblent à des options:

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

Ce qui suit résout cela:

$ bash test.sh -a hello -- -world
h: 0
a: hello

Le --signale une fin des options de ligne de commande, et le -worldbit est laissé au programme pour faire ce qu'il veut (c'est dans l'une des variables de position).

C'est d'ailleurs la façon dont vous supprimez un fichier qui a un tiret au début de son nom de fichier avec rm.

MODIFIER :

Les utilitaires écrits en appel C getopt()(déclarés en unistd.h) fonctionnent de la même manière. En fait, pour autant que nous sachions, la bashfonction getoptspeut être mis en œuvre au moyen d' un appel à la fonction de bibliothèque C getopt(). Perl, Python et d'autres langages ont des bibliothèques d'analyse de ligne de commande similaires, et il est très probable qu'ils effectuent leur analyse de manière similaire.

Certaines de ces routines de bibliothèque getoptet getoptsimilaires gèrent également les options "longues". Celles-ci sont généralement précédées de double tiret ( --), et les options longues qui prennent des arguments le font souvent après un signe égal, par exemple l' --block-size=SIZEoption de [certaines implémentations de] l' duutilitaire (qui permet également -B SIZEde spécifier la même chose).

La raison pour laquelle les manuels sont souvent écrits pour montrer un espace entre les options courtes et leurs arguments est probablement pour la lisibilité.

EDIT : les outils vraiment anciens, tels que les utilitaires ddet tar, ont des options sans tirets devant eux. Ceci est purement pour des raisons historiques et pour maintenir la compatibilité avec les logiciels qui dépendent d'eux pour fonctionner exactement de cette façon. L' tarutilitaire a acquis la possibilité de prendre des options avec des tirets plus récemment. Le manuel BSD pour les tarappels les anciennes options de "drapeaux groupés".

Kusalananda
la source
Cette fonctionnalité peut sembler facile à implémenter dans les scripts bash. Mais je pense que la plupart des utilitaires sont écrits en C (puis compilés en binaires) et non bash. Pourquoi ces utilitaires implémentent-ils cette fonctionnalité?
J.Joe
@ J.Joe Parce qu'ils appellent getopt()(déclaré en unistd.h), ce qui fait la même chose.
Kusalananda
2
Oui, vous avez raison. Référence . Cela résout également un autre mystère que les options peuvent être combinées -a -b=== -ab
J.Joe
1
Les arguments facultatifs pour les drapeaux créeraient une ambiguïté, donc ils ne peuvent pas être combinés (si -aa un argument facultatif, -abn'est pas le même que -a -b). GNU getopt n'arrête pas le traitement des drapeaux lors de la rencontre d'un non-drapeau: à la place (par défaut), il remanie les drapeaux à l'avant d'argv.
ilkkachu
@ilkkachu Merci pour cette clarification. Je pourrai mettre à jour ma réponse plus tard.
Kusalananda
4

xargsest l'un des utilitaires POSIX. Comme l'a commenté @drewbenn, POSIX documente le comportement d'analyse des options pour la plupart de ses utilitaires pour correspondre getopt, avec quelques allocations pour d'autres implémentations, en disant dans 12.1 Syntaxe de l'argument utilitaire :

Cette section décrit la syntaxe des arguments des utilitaires standard et présente la terminologie utilisée dans POSIX.1-2008 pour décrire les arguments traités par les utilitaires.

Dans POSIX.1-2008, une notation spéciale est utilisée pour décrire la syntaxe des arguments d'un utilitaire. Sauf indication contraire , toutes les descriptions d'utilitaires utilisent cette notation, qui est illustrée par cet exemple (voir Commandes simples XCU ):

et concluant avec

Il est recommandé que tous les futurs utilitaires et applications utilisent ces directives pour améliorer la portabilité des utilisateurs. Le fait que certains utilitaires historiques ne puissent pas être modifiés (pour éviter de casser les applications existantes) ne devrait pas décourager cet objectif futur.

Dans POSIX (rappelez-vous qu'il ne couvre que les utilitaires les plus couramment utilisés), il existe des exceptions qui transmettent des opérandes qui seraient des options dans d'autres utilitaires en tant que paramètres positionnels ou paramètres avec une syntaxe spéciale :

POSIX permet des valeurs d'option facultatives :

Les arguments d'option sont affichés séparés de leurs options par des <blank>caractères, sauf lorsque l'argument d'option est inclus dans la notation '['et ']'pour indiquer qu'il est facultatif.

Offhand, je ne me souviens pas quels utilitaires POSIX utilisent la fonction. Les ncurses ticet les infocmputilitaires utilisent la fonction pour les niveaux de l' -voption (verbose / debug).

Le point précis que vous avez demandé est détaillé dans la suite de ce paragraphe, sur plusieurs lignes.

Avant POSIX, certaines implémentations d' psoptions acceptées sans trait d'union. La description POSIX ne mentionne pas cela dans la description de l'utilitaire ou dans la logique de la syntaxe:

Mis à part POSIX, il existe des implémentations à options longues (telles que GNU getopt_long ou X Toolkit ), utilisant une variété de façons de séparer ou de joindre la valeur d'une option à l'option. Par exemple, la ponctuation peut être utilisée:

--option=value
--option value

Selon l'implémentation, un double tiret peut / ne peut pas être utilisé pour distinguer les options longues des options courtes (getopt): lynx et X Toolkit utilisent un seul tiret; GNU getopt_longutilise un double tiret, par exemple. De plus, un +peut être utilisé pour indiquer qu'une option est annulée.

La description de POSIX ne semble en mentionner aucun, mais vous êtes certainement susceptible de les rencontrer.

Thomas Dickey
la source
Est -option=valuecensé l'être --option=value? (Le format à option longue, deux tirets au début au lieu d'un)
J.Joe
Quelques utilitaires hérités utilisent des options longues à tiret unique (-option) mais ils sont largement obsolètes pour les nouveaux scripts et programmes. Utilisez un tiret unique pour les options courtes gérées par getopt. Presque tous les nouveaux scripts et programmes utilisent des options longues à double tiret. Beaucoup prennent également en charge les équivalents d'options courts à tiret unique pour les plus couramment utilisés. Les options longues rendent le code de script beaucoup plus auto-documenté, nécessitant moins de commentaires.
DocSalvager