Habituellement, $0
dans un script est défini sur le nom du script, ou sur ce qu'il a été appelé (y compris le chemin d'accès). Cependant, si j'utilise bash
avec l' -c
option, $0
est défini sur le premier des arguments passés après la chaîne de commande:
bash -c 'echo $0 ' foo bar
# foo
En effet, il semble que les paramètres de position aient été décalés, mais y compris $0
. Cependant, shift
dans la chaîne de commande n'affecte pas $0
(comme d'habitude):
bash -c 'echo $0; shift; echo $0 ' foo bar
# foo
# foo
Pourquoi ce comportement apparemment étrange pour les chaînes de commande? Notez que je cherche la raison, la raison d'être de la mise en œuvre d'un tel comportement étrange.
On pourrait supposer qu'une telle chaîne de commande n'aurait pas besoin du $0
paramètre tel qu'il est généralement défini, donc pour l'économie, il est également utilisé pour les arguments normaux. Cependant, dans ce cas, le comportement de shift
est étrange. Une autre possibilité est celle qui $0
est utilisée pour définir le comportement des programmes (a la bash
appelé as sh
ou vim
appelé as vi
), mais cela ne peut pas l'être, car $0
ici, on ne le voit que dans la chaîne de commande et non par les programmes appelés à l'intérieur. Je ne peux penser à aucune autre utilisation $0
, donc je ne peux pas l'expliquer.
-
pour l'$0
argument comme un idiome, comme danssh -c 'foo $1 $2' - a b
. De cette façon, cela semble assez normal (une fois que vous avez découvert ce que cela-
signifie, c'est-à-dire)echo 'echo the other side of this pipe globs "$@"' | sh -s -- *
, bien que, malheureusement, ce ne$0
soit généralement pas un paramètre définissable avec l'-s
option tream ... Il peut être utilisé de nombreuses manièresxargs
généralement, cependant. Et d'autres d'ailleurs.--
, alors cela aurait pu avoir l'interprétation habituelle de "d'ici commence les arguments", vu dans certains autres programmes. Là encore, cela pourrait confondre ceux qui ne sont pas familiers avec l'-c
idée de--
réellement avoir cette interprétation.Réponses:
Cela vous donne la possibilité de définir / choisir
$0
lorsque vous utilisez un script en ligne. Sinon, ce$0
serait justebash
.Ensuite, vous pouvez faire par exemple:
Tous les obus ne le faisaient pas. Le obus Bourne l'a fait. Le shell Korn (et Almquist) a choisi de faire passer le premier paramètre à la
$1
place. POSIX a finalement opté pour la méthode Bourne,ksh
et lesash
dérivés y sont revenus plus tard (plus à ce sujet sur http://www.in-ulm.de/~mascheck/various/find/#shell ). Cela signifiait que pendant longtempssh
(qui, selon le système, était basé sur le shell Bourne, Almquist ou Korn), vous ne saviez pas si le premier argument était entré$0
ou$1
, donc pour la portabilité, vous deviez faire des choses comme:Ou:
Heureusement, POSIX a spécifié le nouveau comportement où va le premier argument
$0
, nous pouvons donc désormais le faire de manière portable:la source
bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt
sur Ubuntu 14.04, bashversion 4.3.11(1)-release
, et je suis arrivé:txt files are *.txt
. Ootxt
fichiers dans le répertoire courant). Voir aussibash -c 'echo "${1?}"' foo
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt
est incroyablement inventif!SHELL -c 'shift $1; command' 2 1 arg1 arg2 ...
haha ...Ce comportement est défini par POSIX :
Quant à savoir pourquoi vous souhaitez ce comportement: cela atténue l'écart entre un script et une
-c
chaîne. Vous pouvez directement convertir entre les deux sans aucun changement de comportement. D'autres domaines reposent sur le fait qu'ils sont identiques.Il est également conforme au fonctionnement des arguments de programme en général: cela revient finalement à appeler l'une des
exec
fonctions, dans laquelle le premier argument fourni est également$0
, et tout aussi souvent cet argument est le même que l'exécutable que vous exécutez. Parfois, cependant, vous voulez une valeur spéciale là-bas, et il n'y aurait tout simplement pas d'autre moyen de l'obtenir. Étant donné que l'argument existe, il doit correspondre à quelque chose et l'utilisateur doit pouvoir définir ce que c'est.Cette cohérence (et probablement un accident historique) mène à la situation que vous trouvez.
la source
argv[0]
.$0
est uniquement défini sur leargv[0]
passé àexecve()
quand il est commesh
oubash
. Pour les scripts,$0
est défini sur le chemin donné comme argument 1, 2 ... à l'interpréteur (et pour les scripts exécutés directement, cela vient du premier argument de chemin à execve ()).