${var+foo}
expande para foo
se a variável var
estiver definida (mesmo se vazia) e nada de outra forma. Nesse caso, a variável é o primeiro parâmetro posicional, $1
. Portanto, o ${1+"$@"}
verifica se $1
está definido e se expande para "$@"
de acordo e não é nada diferente.
Quanto a $@
e "$@"
, $@
está sujeito a divisão de campo e expansão de nome de arquivo depois de ter expandido para os parâmetros posicionais, enquanto "$@"
não é:
$ sh -c 'cd /usr; printf "%s\n" $@' _ 'a b' '*'
a
b
bin
include
…
$ sh -c 'cd /usr; printf "%s\n" "$@"' _ 'a b' '*'
a b
*
Você quase sempre quer usar "$@"
over $@
.
Quanto a ${1+"$@"}
vs apenas "$@"
, em shells compatíveis com POSIX, ambos teriam o mesmo efeito. De acordo com esta postagem do Stack Overflow :
'Hysterical Raisins', aka Historical Reasons.
Once upon 20 or so years ago, some broken minor variants of the Bourne Shell substituted an empty string
""
for"$@"
if there were no arguments, instead of the correct, current behaviour of substituting nothing. Whether any such systems are still in use is open to debate.
A seção manual autoconf em Substituições de shell também lida com isso:
There are also portability pitfalls with particular expansions:
$@
One of the most famous shell-portability issues is related to ‘
"$@"
’. When there are no positional arguments, Posix says that ‘"$@"
’ is supposed to be equivalent to nothing, but the original Unix version 7 Bourne shell treated it as equivalent to ‘""
’ instead, and this behavior survives in later implementations like Digital Unix 5.0.
Veja também: