Acceder a la línea de comando de bash args $ @ vs $ *

En muchas preguntas de SO y tutoriales bash, veo que puedo acceder a argumentos de línea de comando en scripts bash de dos maneras:

$ ~ >cat testargs.sh #!/bin/bash echo "you passed me" $* echo "you passed me" $@ 

Lo que resulta en:

 $ ~> bash testargs.sh arg1 arg2 you passed me arg1 arg2 you passed me arg1 arg2 

¿Cuál es la diferencia entre $* y $@ ?
¿Cuándo se debe usar el primero y cuándo se debe usar el último?

La diferencia aparece cuando se citan los parámetros especiales. Déjame ilustrar las diferencias:

 $ set -- "arg 1" "arg 2" "arg 3" $ for word in $*; do echo "$word"; done arg 1 arg 2 arg 3 $ for word in $@; do echo "$word"; done arg 1 arg 2 arg 3 $ for word in "$*"; do echo "$word"; done arg 1 arg 2 arg 3 $ for word in "$@"; do echo "$word"; done arg 1 arg 2 arg 3 

un ejemplo más sobre la importancia de las citas: tenga en cuenta que hay 2 espacios entre “arg” y el número, pero si no puedo citar $ word:

 $ for word in "$@"; do echo $word; done arg 1 arg 2 arg 3 

y en bash, "$@" es la lista “predeterminada” para repetir:

 $ for word; do echo "$word"; done arg 1 arg 2 arg 3 

Una buena y útil tabla de descripción general de la Wiki Bash Hackers :

$ * versus $ @ table

Si los argumentos deben almacenarse en una variable de script y se espera que los argumentos contengan espacios, recomiendo encarecidamente emplear un truco "$*" con el separador de campo interno $IFS establecido en tabulación .

ps

Se expande a los parámetros posicionales, comenzando desde uno. Cuando la expansión ocurre entre comillas dobles, se expande a una sola palabra con el valor de cada parámetro separado por el primer carácter de la variable especial IFS. Es decir, “$ *” es equivalente a “$ 1c $ 2c …”, donde c es el primer carácter del valor de la variable IFS. Si IFS no está configurado, los parámetros están separados por espacios. Si IFS es nulo, los parámetros se unen sin separadores intermedios.

ps

Se expande a los parámetros posicionales, comenzando desde uno. Cuando la expansión ocurre entre comillas dobles, cada parámetro se expande a una palabra separada. Es decir, “$ @” es equivalente a “$ 1” “$ 2” … Si la expansión de comillas dobles ocurre dentro de una palabra, la expansión del primer parámetro se une con la parte inicial de la palabra original, y la expansión del último parámetro se une con la última parte de la palabra original. Cuando no hay parámetros posicionales, “$ @” y $ @ se expanden a nada (es decir, se eliminan).

Fuente: Bash man

$ @ es igual a $ *, pero cada parámetro es una cadena entrecomillada, es decir, los parámetros se transmiten intactos, sin interpretación ni expansión. Esto significa, entre otras cosas, que cada parámetro en la lista de argumentos se ve como una palabra separada.

Por supuesto, “$ @” debe ser citado.

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST