Dans la documentation Perl, perlrun (1) suggère de lancer les scripts Perl à l'aide d'un en-tête shell / Perl bilingue:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
Qu'est-ce que ça ${1+"$@"}
veut dire? J'ai essayé d'utiliser à la "$@"
place (en utilisant Bash comme / bin / sh), et cela semble fonctionner aussi bien.
modifier
Deux réponses ci-dessous indiquent que c'est supposé l'être ${1:+"$@"}
. Je connais la ${parameter:+word}
syntaxe ("Use Alternate Value") décrite dans bash (1). Cependant, je ne suis pas convaincu, car
Les deux
${1+"$@"}
et"$@"
fonctionnent très bien, même quand il n'y a pas de paramètres. Si je crée simple.sh en tant que#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
et question.sh comme
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
Je peux obtenir les deux travailler à l'identique:
$ ./question.sh $VAR1 = []; $ ./question.sh a $VAR1 = [ 'a' ]; $ ./question.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./question.sh "" $VAR1 = [ '' ]; $ ./simple.sh $VAR1 = []; $ ./simple.sh a $VAR1 = [ 'a' ]; $ ./simple.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./simple.sh "" $VAR1 = [ '' ];
D'autres sources sur Internet utilisent également
${1+"$@"}
, y compris un pirate qui semble savoir ce qu'il fait.
Peut ${parameter+word}
- être une syntaxe alternative non documentée (ou obsolète) pour ${parameter:+word}
? Quelqu'un pourrait-il confirmer cette hypothèse?
Réponses:
C'est pour la compatibilité avec le shell Bourne. Le shell Bourne était un ancien shell sorti avec la version 7 d'Unix en 1979 et qui était encore courant jusqu'au milieu des années 90, comme
/bin/sh
sur la plupart des Unices commerciaux.C'est l'ancêtre de la plupart des coquillages semblables à Bourne
ksh
,bash
ouzsh
.Il comportait quelques fonctionnalités peu pratiques, dont beaucoup ont été corrigées
ksh
, les autres coques et la nouvelle spécification standard desh
, dont l’une est la suivante:Avec le shell Bourne (au moins les variantes pour lesquelles il n’a pas été corrigé): se
"$@"
développe en un argument vide si la liste des paramètres de position est empty ($# == 0
) au lieu d’aucun argument.${var+something}
se développe en "quelque chose" à moins que$var
non défini. Il est clairement documenté dans tous les réservoirs, mais difficile à trouver dans labash
documentation car vous devez faire attention à cette phrase:Donc,
${1+"$@"}
étend"$@"
seulement à if si$1
set ($# > 0
) qui contourne cette limitation du shell Bourne.Notez que le shell Bourne est le seul shell avec ce problème. Modern
sh
s (sh
conforme à la spécification POSIX desh
(ce que le shell Bourne n'est pas)) n'a pas ce problème. Donc, vous n’avez besoin de cela que si vous avez besoin de votre code pour fonctionner sur de très vieux systèmes où il/bin/sh
pourrait s’agir d’un shell Bourne au lieu d’un shell standard (notez que POSIX ne spécifie pas l’emplacement de la normesh
, donc par exemple sous Solaris avant Solaris 11,/bin/sh
était toujours un shell Bourne (bien qu’il n’ait pas ce problème particulier) alors que le standard / standard sesh
trouvait dans un autre emplacement (/usr/xpg4/bin/sh
)).Il y a un problème dans cette
perlrun
page perldoc qui$0
n'est pas cité.Voir http://www.in-ulm.de/~mascheck/various/bourne_args/ pour plus d'informations.
la source
Il y a une différence entre:
et
Dans l'un, vous passez un argument qui est une chaîne vide. Dans le second cas, aucun argument n'a été transmis.
Pour les deux, « $ @ » correspondra à la même chose:
""
. Mais utiliser${1:+"$@"}
serait""
pour le premier et aucun argument ne serait transmis pour le second, ce qui était l'intention.Cela devient important si vous exécutez quelque chose dans le script ci-dessous, appelé sshwrapper, que vous appelez avec une commande facultative ou sans argument pour obtenir un shell interactif.
Cela essaierait de s'exécuter "" sur l'hôte distant (qui ne fait que revenir), ce ne serait pas un shell interactif.
Lancerait un shell interactif sur l'hôte distant, car l'exécutable interpréterait correctement la variable comme étant nulle, pas une chaîne vide.
Consultez l’utilisation de "$ {paramètre: + mot}" ("Utiliser une autre valeur") et des chaînes d’extension de variable similaires dans les pages de manuel de bash.
la source
sh
implémentation conforme à POSIX (voir autre réponse).${1:+"$@"}
ne développerait aucun argument si$1
était vide. Vous voulez${1+"$@"}
. En gros, vous l'avez inversé.J'ai résumé la réponse de Stéphane Chazelas:
Donc, si utiliser le second avec le paramètre "", cela signifie que $ 1 est nul, mais il ne vérifie pas si c'est nul ou pas, il voit juste qu'il a déjà été réglé, mais qu'il soit vide ou non, donc il développera $ @ , mais vous utilisez $ {1: + "$ @"} 'avec "", il ne s’étendra
$@
plus.la source