Usualmente $@
representamos todos los argumentos excepto $ 0. Sin embargo, no sé qué $@
es la estructura de datos .
¿Por qué se comporta de manera diferente $*
cuando se incluye entre comillas dobles, alguien podría darme una explicación a nivel de intérprete?
Se puede iterar en el bucle for, por lo que parece ser una matriz. Sin embargo, también puede repetirse completamente con simple echo $@
, si es una matriz, solo se mostrará el primer elemento. Debido a la limitación de shell, no puedo escribir más código de experimento para llevarlo a cabo.
Diferencia entre esta publicación : Esta publicación muestra cómo se $@
comporta de manera diferente $*
. Pero me pregunto sobre el tipo de datos de $@
. Shell como lenguaje de interpretación, como Python, debe representar los datos de acuerdo con una serie de tipos fundamentales. O en otras palabras, quiero saber cómo $ @ se almacena en la memoria de la computadora.
¿Es una cadena, una cadena de varias líneas o una matriz?
Si es un tipo de datos único, ¿es posible definir una variable personalizada como una instancia de este tipo?
printf '%s\n' "$@"
yprintf '%s\n' "$*"
. Laecho
utilidad solo genera sus argumentos, sin importar si son uno o varios. Ambas son matrices (de cadenas), pero se comportan de manera diferente cuando se citan dos veces. Si cualquiera era una cadena de varias líneas, entonces no podrían almacenar cadenas de varias líneas (que pueden). No está claro qué problema está tratando de resolver.@var
variable en Perl, en términos de su almacenamiento subyacente. Desde el punto de vista de un programa Perl ordinario, realmente no importa, aparte de eso, es accesible como una matriz / lista (y el hecho de que hay contextos en los que se espera una lista).Respuestas:
Eso comenzó como un truco en el shell Bourne. En el shell Bourne, la división de palabras IFS se realizó (después de la tokenización) en todas las palabras en el contexto de la lista (argumentos de línea de comando o las palabras en las que se
for
repiten los bucles). Si tuvieras:Esa segunda línea se tokenised en 3 palabras,
$var
se ampliaría, y dividir + glob se llevaría a cabo en las tres palabras, por lo que terminaría corriendoed
cont
,f
,le.txt
,f
,le2.txt
como argumentos.Citar partes de eso evitaría la división + glob. El shell Bourne inicialmente recordó qué caracteres fueron citados al establecer el octavo bit en ellos internamente (eso cambió más tarde cuando Unix se limpió a 8 bits, pero el shell aún hizo algo similar para recordar qué byte fue citado).
Ambos
$*
y$@
fueron la concatenación de los parámetros posicionales con espacio intermedio. Pero hubo un procesamiento especial de$@
cuándo dentro de comillas dobles. Si está$1
contenidofoo bar
y$2
contenidobaz
,"$@"
se expandiría a:(con la
^
s anterior que indica cuáles de los caracteres tienen el octavo bit establecido). Donde se citó el primer espacio (tenía el octavo bit establecido) pero no el segundo (el agregado entre palabras).Y es la división IFS la que se encarga de separar los argumentos (suponiendo que el carácter de espacio esté
$IFS
como está por defecto). Es similar a cómo$*
se expandió en su predecesor el shell Mashey (basado en el shell Thomson, mientras que el shell Bourne se escribió desde cero).Eso explica por qué en el shell Bourne inicialmente
"$@"
se expandiría a la cadena vacía en lugar de nada en absoluto cuando la lista de parámetros posicionales estaba vacía (tenía que evitarlo${1+"$@"}
), por qué no mantuvo los parámetros posicionales vacíos y por qué"$@"
no no funciona cuando$IFS
no contiene el carácter de espacio.La intención era poder pasar la lista de argumentos literalmente a otro comando, pero eso no funcionó correctamente para la lista vacía, para elementos vacíos o cuando
$IFS
no contenía espacio (los dos primeros problemas finalmente se solucionaron en versiones posteriores )El shell Korn (en el que se basa la especificación POSIX) cambió ese comportamiento de varias maneras:
edit
ofile.txt
en el ejemplo anterior)$*
y$@
se unen con el primer carácter de$IFS
o espacio cuando$IFS
está vacío, excepto que para una cita"$@"
, esa unión no se cita como en el shell Bourne, y para una cita"$*"
cuandoIFS
está vacía, los parámetros posicionales se agregan sin separador.${array[@]}
${array[*]}
reminiscencia de Bourne de$*
y$@
pero a partir de indice 0 en lugar de 1, y escasa (más como matrices asociativas) lo que significa$@
realmente no pueden ser tratados como una matriz de ksh (comparar concsh
/rc
/zsh
/fish
/yash
donde$argv
/$*
son normales matrices)."$@"
cuando$#
es 0 ahora se expande a nada en lugar de la cadena vacía,"$@"
funciona cuando$IFS
no contiene espacios, excepto cuandoIFS
está vacío. Un$*
sin comillas sin comodines se expande a un argumento (donde los parámetros posicionales se unen con el espacio) cuando$IFS
está vacío.ksh93 solucionó los pocos problemas restantes anteriores. En ksh93,
$*
y se$@
expande a la lista de parámetros posicionales, separados independientemente del valor de$IFS
, y luego se divide + globbed + brace-expandido en contextos de lista,$*
unido con el primer byte (no carácter) de$IFS
,"$@"
en contextos de lista se expande a la lista de parámetros posicionales, independientemente del valor de$IFS
. En un contexto que no es de lista, como envar=$@
,$@
se une con espacio independientemente del valor de$IFS
.bash
Las matrices están diseñadas después de las ksh. Las diferencias son:$IFS
lugar de por byte$*
cuando no se cita en un contexto sin lista cuando$IFS
está vacío.Si bien la especificación POSIX solía ser bastante vaga, ahora más o menos especifica el comportamiento bash.
Es diferente de las matrices normales en
ksh
obash
en eso:"${@:0}"
que incluye$0
(no es un parámetro posicional, y en funciones le da el nombre de la función o no dependiendo del shell y cómo se definió la función)).shift
puede ser usado.En
zsh
oyash
donde las matrices son matrices normales (no dispersas, los índices comienzan en uno como en todos los demás shells pero ksh / bash),$*
se trata como una matriz normal.zsh
tiene$argv
como un alias para ello (por compatibilidad concsh
).$*
es lo mismo que$argv
or${argv[*]}
(argumentos unidos con el primer carácter de$IFS
pero aún separados en contextos de lista). Me"$@"
gusta"${argv[@]}"
o se"${*[@]}"}
somete al procesamiento especial de estilo Korn.fuente
Es un parámetro especial que se expande a los valores de los parámetros posicionales ... Pero eso no es nada específico sobre la terminología.
Podemos ver los parámetros posicionales como partes de
$@
, por lo que tiene una serie de elementos distintos ($1
,$2
...), a los que se puede acceder de forma independiente y se nombran por números naturales consecutivos. Eso lo convierte en algo que generalmente se llama una matriz.Sin embargo, la sintaxis es un poco extraña e incluso limitada. No hay forma de modificar un solo elemento de la matriz individualmente. En cambio, todo se debe configurar de una vez. (Puede usar
set -- "$@" foo
para agregar un valor oset -- "${@:1:2}" foo "${@:3}"
para agregar un valor en el medio. Pero en ambos casos debe escribir toda la lista resultante).Porque están definidos para comportarse de manera diferente.
Si te refieres al hecho de que solo
a=(foo bar asdf); echo $a
dará salidafoo
, entonces esto es principalmente una peculiaridad de la sintaxis de shell, y el hecho de que las matrices con nombre de estilo ksh se crearon más tarde que los parámetros de posición y$@
. Plain$a
es el mismo${a[0]}
que tiene el significado compatible con versiones anteriores de un solo valor escalar, independientemente de sia
es una matriz o una variable escalar simple.El
@
signo que se refiere a la lista completa se reutilizó con matrices con nombre, ya que"${a[@]}"
es la forma de obtener la lista completa. En comparación con las matrices con$@
nombre, solo se omiten las llaves y los corchetes innecesarios y el nombre.Eso depende de la implementación, tendrá que buscar el código fuente de cualquier shell particular que le interese.
Una matriz, en su mayoría. Aunque son diferentes de las matrices con nombre de estilo ksh, ya que pueden tener enteros arbitrarios no negativos como índices, no solo los consecutivos como con
$@
. (Es decir, una matriz denominada puede ser escasa, y tienen por ejemplo los índices1
,3
y4
, con0
y2
que falta. Eso no es posible con los parámetros posicionales.)No es una sola cadena, ya que se puede expandir a elementos distintos, y llamar a las líneas de elementos tampoco es correcto, ya que cualquier variable regular o uno de los parámetros posicionales (elementos de
$@
) también pueden contener nuevas líneas.No. Pero las matrices con nombre son probablemente más útiles de todos modos.
fuente
$@
no es una estructura de datos, es una de las pocas funciones / operadores para expandir la estructura de datos de parámetros posicionales.