Qual é a diferença entre $ @ e $ * [duplicado]

26

De acordo com esta 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 hits do google, não consigo encontrar nenhuma explicação sobre por que haveria duas sintaxes aparentemente duplicadas.

Eles parecem funcionar da mesma forma nos 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
  1. Um é preferido em detrimento do outro?
  2. Por que existem duas variáveis internas para fazer exatamente a mesma coisa?

Fontes adicionais
bash.cyberciti.biz

    
por spuder 12.05.2014 / 18:07

4 respostas

49

Eles não são iguais. $* é uma única string, enquanto $@ é uma matriz real. Para ver a diferença, execute o seguinte script da seguinte forma:

 > ./test.sh one two "three four"

O script:

#!/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              

Os quatro casos são:

Using "$*":
one two three four

Aqui, os parâmetros são considerados como uma string longa citada . Sem aspas:

Using $*:
one
two
three
four

A string é dividida em palavras pelo loop for .

Using "$@":
one
two
three four

Isso trata cada elemento de $ @ como uma string entre aspas.

Using $@:
one
two
three
four

Isso trata cada elemento como uma string sem aspas, então o último é novamente dividido pelo que equivale a for three four .

    
por 12.05.2014 / 18:23
12

A diferença vem 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 ).
$@ 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>
    
por 12.05.2014 / 18:17
3

Você pode analisar o Guia do Bash Beginners para obter mais informações. Estes para fazer praticamente a mesma coisa com a diferença de como ela é separada:

$* - Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable.

$@ - Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word.

Mas, a menos que você defina IFS para valorar outro, o padrão poderá ser idêntico.

    
por 12.05.2014 / 18:16
0

Is one preferred over the other?

Uma resposta curta é "$@" .

Se você usá-los sem aspas duplas, eles são os mesmos. Não há ninguém preferido sobre o outro neste caso. Mas sugiro que você sempre as use com aspas duplas, exceto que você sabe exatamente o que quer.

Why are there 2 builtin variables to do the exact same thing?

Não há diferença entre $* e $@ , mas "$@" e "$*" têm.

Você pode ver minha resposta em esta postagem para ver como são diferentes?

    
por 12.05.2014 / 18:24

Tags