De acordo comesta página, $@ e $* fazem praticamente a mesma coisa:
The $@ holds list of all arguments passed to the script.
The $* holds list of all arguments passed to the script.
Depois de pesquisar todos os principais resultados no Google, não consigo encontrar nenhuma explicação de por que haveria duas sintaxes aparentemente duplicadas.
Eles parecem funcionar da mesma forma em meus scripts.
cat foo.sh
#!/bin/bash
echo The parameters passed in are $@
echo The parameters passed in are $*
./foo.sh herp derp
The parameters passed in are herp derp
The parameters passed in are herp derp
- Um é preferido ao outro?
- Por que existem 2 variáveis internas para fazer exatamente a mesma coisa?
Fontes adicionais
bash.cyberciti.biz
Responder1
Eles não são iguais. $*
é uma única string, enquanto $@
é uma matriz real. Para ver a diferença, execute o seguinte script assim:
> ./test.sh one two "three four"
O roteiro:
#!/bin/bash
echo "Using \"\$*\":"
for a in "$*"; do
echo $a;
done
echo -e "\nUsing \$*:"
for a in $*; do
echo $a;
done
echo -e "\nUsing \"\$@\":"
for a in "$@"; do
echo $a;
done
echo -e "\nUsing \$@:"
for a in $@; do
echo $a;
done
A explicação e os resultados para os quatro casos estão abaixo.
No primeiro caso, os parâmetros são considerados como um longocitadocorda:
Using "$*":
one two three four
Caso 2 (sem aspas) - a string é dividida em palavras pelo for
loop:
Using $*:
one
two
three
four
Caso 3 - trata cada elemento de $@ como uma string entre aspas:
Using "$@":
one
two
three four
Último caso - trata cada elemento como uma string sem aspas, então o último é novamente dividido pelo valor for three four
:
Using $@:
one
two
three
four
Responder2
A diferença está em como eles são expandidos.
$*
expande para um único argumento com todos os elementos delimitados por espaços (na verdade, o primeiro caractere de $IFS
).
$@
se expande para vários argumentos.
Por exemplo
#!/bin/bash
echo "With *:"
for arg in "$*"; do echo "<$arg>"; done
echo
echo "With @:"
for arg in "$@"; do echo "<$arg>"; done
$ /tmp/test.sh 1 2 "3 4"
With *:
<1 2 3 4>
With @:
<1>
<2>
<3 4>
Responder3
Você pode revisarGuia para iniciantes do BashPara maiores informações. Eles fazem praticamente a mesma coisa, com a diferença de como são separados:
$*
- Expande para os parâmetros posicionais, começando em um. Quando a expansão ocorre entre aspas duplas, ela se expande para uma única palavra com o valor de cada parâmetro separado pelo primeiro caractere da variável especial IFS.
$@
- Expande para os parâmetros posicionais, começando em um. Quando a expansão ocorre entre aspas duplas, cada parâmetro se expande para uma palavra separada.
Mas, a menos que você defina IFS
um valor diferente do padrão, ele poderá parecer idêntico.
Responder4
Um é preferido ao outro?
Uma resposta curta é "$@"
.
Se você usá-los sem aspas duplas, eles serão iguais. Não há ninguém preferido sobre o outro neste caso. Mas eu sugiro que você sempre os use com aspas duplas, a menos que você saiba exatamente o que deseja.
Por que existem 2 variáveis internas para fazer exatamente a mesma coisa?
Não há diferença entre $*
e $@
, mas "$@"
e "$*"
tem.
Você pode ver minha resposta emesta postagempara ver como eles são diferentes.