Na documentação do Perl, o perlrun (1) sugere o lançamento de scripts Perl usando um cabeçalho bilíngue do shell / Perl:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
O que ${1+"$@"}
significa isso ? Tentei usar "$@"
(em vez disso, usando Bash como / bin / sh), e parece funcionar da mesma forma.
Editar
Duas respostas abaixo dizem que deveria ser ${1:+"$@"}
. Estou ciente da ${parameter:+word}
sintaxe ("Usar valor alternativo") documentada no bash (1). No entanto, não estou convencido, porque
Ambos
${1+"$@"}
e"$@"
funcionam muito bem, mesmo quando não há parâmetros. Se eu criar simple.sh como#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
e question.sh como
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
Posso fazer com que ambos trabalhem de forma idêntica:
$ ./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 = [ '' ];
Outras fontes na Internet também usam
${1+"$@"}
, incluindo um hacker que parece saber o que está fazendo.
Talvez ${parameter+word}
seja uma sintaxe alternativa (ou obsoleta) indocumentada para ${parameter:+word}
? Alguém poderia confirmar essa hipótese?
Respostas:
Isso é compatível com o shell Bourne. O shell Bourne era um shell antigo que foi lançado pela primeira vez com a versão 7 do Unix em 1979 e ainda era comum até meados dos anos 90, como
/bin/sh
na maioria dos Unices comerciais.É o ancestral da maioria das conchas tipo Bourne
ksh
, como ,bash
ouzsh
.Tinha algumas características estranhas, muitas das quais foram fixadas
ksh
e as outras conchas e a nova especificação padrão desh
, uma das quais é esta:Com o shell Bourne (pelo menos as variantes em que não foi corrigido):
"$@"
expande para um argumento vazio se a lista de parâmetros posicionais estiver vazia ($# == 0
) em vez de nenhum argumento.${var+something}
expande para "alguma coisa", a menos que$var
esteja desativado. Está claramente documentado em todas as conchas, mas é difícil de encontrar nabash
documentação, pois você precisa prestar atenção a esta frase:Portanto,
${1+"$@"}
expande"$@"
apenas se$1
for definido ($# > 0
), que contorna essa limitação do shell Bourne.Observe que o shell Bourne é o único shell com esse problema. Os
sh
s modernos (que estão emsh
conformidade com a especificação POSIX desh
(que o shell Bourne não é)) não têm esse problema. Portanto, você só precisa disso se precisar que seu código funcione em sistemas muito antigos, onde/bin/sh
pode ser um shell Bourne em vez de um shell padrão (observe que o POSIX não especifica a localização do padrãosh
, por exemplo, no Solaris antes do Solaris 11,/bin/sh
ainda era um shell Bourne (embora não tivesse esse problema específico) enquanto o normal / padrãosh
estava em outro local (/usr/xpg4/bin/sh
)).Há um problema nessa
perlrun
página perldoc que$0
ainda não é citado.Veja http://www.in-ulm.de/~mascheck/various/bourne_args/ para mais informações.
fonte
Há uma diferença entre:
e
Em um, você está passando um argumento que é uma string vazia. No segundo, não há argumentos passados.
Para ambos, "$ @" vai equiparar à mesma coisa:
""
. Mas usar${1:+"$@"}
seria""
para o primeiro e nenhum argumento passaria para o segundo, que era a intenção.Isso se torna importante se você estiver executando algo do script abaixo, chamado sshwrapper, que você chama com um comando opcional ou sem argumentos para obter um shell interativo.
Isso tentaria executar "" no host remoto (que retorna), não seria um shell interativo.
Iniciava um shell interativo no host remoto porque o exec interpretaria corretamente a variável como nada, não como uma sequência vazia.
Leia sobre o uso de "$ {parameter: + word}" ("Use Alternate Value") e cadeias de expansão variáveis semelhantes nas páginas de manual do bash.
fonte
sh
implementação compatível com POSIX (consulte outra resposta).${1:+"$@"}
seria expandido para nenhum argumento se$1
estivesse vazio. Você quer${1+"$@"}
. Basicamente, você o inverteu.Resumi a resposta de Stéphane Chazelas:
portanto, se usar o segundo com o parâmetro "", isso significa que $ 1 é nulo, mas não testa se é nulo ou não, basta ver que já foi definido, no entanto, está vazio ou não e, portanto, expandirá $ @ , mas você usa $ {1: + "$ @"} 'com "", ele não será mais expandido
$@
.fonte