Ar

Arrays en Bash

{one: "1 ejercicio", many: "%{count} de ejercicios", other: "%{count} ejercicios"}

Acerca de Arrays

Bash proporciona dos tipos de parámetros: valores «escalares» y arrays. Un valor escalar puede ser un string o un número; representa una sola «cosa».

La mayoría de las veces, los valores escalares son suficientes para contener tus datos. Pero a veces necesitas almacenar una lista de valores escalares. En ese caso usarás un array.

Hay dos tipos de arrays:

  • Los arrays indexados numéricamente asignan una clave entera a un valor de tipo string. (Otros lenguajes podrían llamar a esto una «lista» o una «secuencia»).
  • Los arrays asociativos asignan una clave de tipo string a un valor de tipo string. (Otros lenguajes podrían llamar a esto un «mapa» o un «diccionario»).

Las primeras secciones de este documento cubrirán los arrays indexados numéricamente (de aquí en adelante, simplemente «arrays»). Los detalles sobre los arrays asociativos aparecerán al final.

Caution

Los arrays de Bash solo pueden almacenar valores escalares. No es posible crear un array bidimensional (array de arrays).

Declarar e inicializar una variable de array

Puedes inicializar un array asignando una lista de elementos entre paréntesis (posiblemente vacía) a una variable.

myarray=("one" "two" "three")

Como ocurre con toda asignación de variable, no debe haber espacios alrededor del signo igual.

Ten en cuenta que no hay comas que separen los elementos; es una lista de strings separada por espacios en blanco.

De hecho, la cantidad de espacios en blanco dentro de los paréntesis es completamente arbitraria. Se permiten saltos de línea; usa tantos como quieras para mejorar la legibilidad.

myarray=(
    "first element"
    "second element"
    "this is the last element"
)

Asignar una lista de strings a una variable de array de esta manera almacenará el primer string en el índice cero, el siguiente string en el índice uno, el siguiente en el índice dos, y así sucesivamente.

Es posible inicializar un «array disperso» especificando los índices que necesitas.

raindrops=([3]="Pling" [5]="Plang" [7]="Plong")
Note

Para reiterar: los índices de los arrays empiezan en cero. Este fragmento imprime «true»:

myarray=("one" "two" "three")
[[ "${myarray[0]}" == "one" ]] && echo true || echo false

Puedes usar el comando declare (o local dentro de una función) para especificar que una variable contendrá un array.

declare -a myarray

Es más idiomático simplemente asignar una lista entre paréntesis (quizás vacía) para inicializar la variable.

Acceder a los elementos de un array

Como viste en la nota anterior, la sintaxis para acceder a un elemento de un array es ${myarray[$index]}. El índice se da entre corchetes. Las llaves son obligatorias.

Note

Para los arrays indexados numéricamente, el índice es una expresión aritmética. El manual de Bash afirma:

Dentro de una expresión aritmética, las variables del shell también pueden referenciarse por nombre sin usar la sintaxis de expansión de parámetros.

Esto significa que el $ no es necesario para la expansión «simple» de variables. Puedes acceder a los elementos así, lo que es un poco más fácil de leer:

i=5
echo "${myarray[i]}"
# ..............^

Si el índice dado no existe en el array, el resultado de la expansión es un string vacío.

Asignar a un array

Para asignar a una entrada particular del array, usa esta sintaxis:

myarray[10]="hello"

Para agregar a un array, usa el operador de asignación por concatenación +=, y usa paréntesis:

myarray+=("new element 1" "new element 2")

Iterar sobre un array

Normalmente necesitarás iterar sobre los valores de un array. Usa un bucle for (que viste en el concepto bucle):

myarray=("one" "two" "three")
for value in "${myarray[@]}"; do
    echo "$value"
done

Fíjate en la sintaxis especial para expandir el array: "${myarray[@]}" Esta forma de expansión de parámetros sustituye los valores del array como palabras separadas. Es algo equivalente a:

for value in "${myarray[0]}" "${myarray[1]}" ... "${myarray[n]}"

La forma "${myarray[@]}" funciona con arrays dispersos, expandiéndose solo a los valores definidos.

Esta expansión especial, donde el índice es una arroba (@), solo es especial dentro de comillas dobles.

Otras expansiones de parámetros especiales

Aquí hay otro par de sintaxis especiales que necesitamos para iterar sobre un array. Se describen en el manual en Expansión de parámetros del shell.

Para encontrar la longitud de un array, usa ${#myarray[@]}, con un # antes del nombre. La «longitud» de un array significa la cantidad de elementos que contiene.

Para extraer la lista de índices de un array, usa "${!myarray[@]}", con un ! antes del nombre y la expansión entre comillas dobles. Para los arrays indexados numéricamente, los índices se expanden en orden numérico.

Iterar sobre los índices de un array

A veces necesitas el índice además del valor. Hay un par de formas de hacerlo.

  1. Cuando sabes que los índices forman una secuencia ininterrumpida, puedes usar un bucle for aritmético.

    for ((i = 0; i < ${#myarray[@]}; i++)); do
        echo "$i -> ${myarray[i]}"
    done
    

    Fíjate en la sintaxis ${#myarray[@]}, con el carácter # delante del nombre del array. Como los arrays usan indexación basada en cero, el último índice del array es uno menos que la longitud del array.

  2. Cuando el array es disperso, puedes usar esta forma:

    for index in "${!raindrops[@]}"; do
        echo "$index -> ${raindrops[index]}"
    done
    

    Fíjate en la sintaxis ${!myarray[@]}, con el carácter ! delante del nombre del array.

Inspeccionar un array

Si quieres ver el contenido de un array, usa el comando declare con la opción -p:

a=("the 'first' element"
   second
   third
   'the "last" element')
declare -p a

Esto muestra el contenido con el entrecomillado canónico del shell.

declare -a a=([0]="the 'first' element" [1]="second" [2]="third" [3]="the \"last\" element")

Arrays asociativos

Para reiterar, los arrays asociativos usan strings como índices, no números. Todo lo escrito anteriormente se aplica a los arrays asociativos, pero con pequeñas diferencias. En general, usamos el término «clave», no «índice»: los arrays asociativos asignan claves a valores.

Declarar un array asociativo

A diferencia de los arrays, los arrays asociativos deben declararse. Usa la opción -A de declare (o local en una función):

declare -A mymap

myfunc() {
    local -A my_local_map
    # ...
}

Inicializar un array asociativo

Los pares clave-valor se especifican dentro de la lista entre paréntesis:

mymap=([first]=foo [second]=bar [third]=baz)
declare -p mymap

Esto muestra:

declare -A mymap=([second]="bar" [first]="foo" [third]="baz")
Note

Ten en cuenta que los arrays asociativos no tienen orden.

La declaración y la inicialización pueden ocurrir en una sola línea.

declare -A mymap=([first]=foo [second]=bar [third]=baz)

En versiones recientes de Bash, la inicialización puede usar una lista (key value key value ...).

declare -A mymap=(first foo second bar third baz)

Acceder a los valores

Se usa la misma sintaxis que antes para acceder a los elementos: ${mymap[$key]}.

Las claves de los arrays asociativos no se evalúan en un contexto aritmético. Se requiere la sintaxis habitual de expansión de parámetros.

Asignar a un array asociativo

La asignación usa la misma sintaxis que antes:

mymap[$key]="$value"

Iterar

Puedes usar un bucle for value in "${mymap[@]}" para iterar. Sin embargo, normalmente también quieres la clave junto con el valor.

Usa la sintaxis "${!mymap[@]}" que vimos antes.

for key in "${!mymap[@]}"; do
    echo "$key -> ${mymap[$key]}"
done

Esto muestra

second -> bar
first -> foo
third -> baz

Para recalcar, no hay ningún orden en las claves.

Editar en GitHub El enlace se abre en una ventana o pestaña nueva