6. Arrays y Gestión de Colecciones

En Bash, un array es una variable que puede almacenar múltiples valores. Son muy útiles cuando queremos guardar listas de elementos (archivos, usuarios, números, etc.) y procesarlos más tarde con bucles.

Este módulo te permitirá trabajar con colecciones simples y asociativas, acceder a valores por índice, añadir elementos y recorrer los arrays.


1. Arrays Indexados

Los arrays indexados usan números enteros como índices, empezando por 0.

1.1 Crear un array

Varias formas:





nombres=("Ana" "Luis" "Carlos")

o





nombres[0]="Ana"
nombres[1]="Luis"
nombres[2]="Carlos"

1.2 Acceder a elementos

Acceso mediante índices:





echo ${nombres[0]}

Salida:





Ana

1.3 Mostrar todos los elementos





echo ${nombres[@]}

o





echo ${nombres[*]}

1.4 Contar elementos





echo ${#nombres[@]}

Ejemplo:





nombres=("Ana" "Luis" "Carlos")
echo ${#nombres[@]}    # muestra 3

Cuando trabajas con arrays:

SímboloEjemploSignificado
@${array[@]}Todos los elementos del array por separado.
*${array[*]}Todos los elementos como una única cadena.
#${#array[@]}Número de elementos del array.
[]${array[2]}Acceder al índice 2 del array.


${array[@]} y ${array[*]} parecen iguales, pero no lo son cuando hay espacios:

  • "${array[@]}" → cada elemento es una palabra independiente
  • "${array[*]}" → todo se convierte en una única cadena

Esto afecta a bucles, argumentos, etc.

1.5 Añadir elementos





nombres+=("Sofía")

o por índice:





nombres[3]="Sofía"

1.6 Eliminar elementos

Se puede borrar un índice concreto:





unset nombres[1]

Esto no reorganiza los índices, simplemente deja un “hueco”.


2. Recorrer Arrays

La manera más común es con for:





nombres=("Ana" "Luis" "Carlos")

for nombre in "${nombres[@]}"; do
    echo "Nombre: $nombre"
done

Salida:





Nombre: Ana
Nombre: Luis
Nombre: Carlos

3. Arrays Asociativos

Los arrays asociativos permiten guardar pares clave → valor, similar a diccionarios o mapas.

3.1 Declaración

Hay que declararlos antes:





declare -A capitales

3.2 Asignación





capitales[España]="Madrid"
capitales[Francia]="París"
capitales[Italia]="Roma"

3.3 Acceso por clave





echo ${capitales[Francia]}

Salida:





París

3.4 Listar claves





echo ${!capitales[@]}

3.5 Listar valores





echo ${capitales[@]}

4. Casos de uso comunes

4.1 Guardar usuarios del sistema





usuarios=($(cut -d: -f1 /etc/passwd))

4.2 Guardar archivos por extensión





imagenes=(*.jpg *.png *.gif)

4.3 Guardar resultados de un comando





procesos=($(ps -e | awk '{print $1}'))

5. Simbologías en bash

En Bash aparecen unos símbolos “místicos” que parecen sacados de la iconografía nórdica (@, *, #, etc.) y que tienen significados distintos según el contexto.


a) En arrays Bash

Cuando trabajas con arrays:

SímboloEjemploSignificado
@${array[@]}Todos los elementos del array por separado.
*${array[*]}Todos los elementos como una única cadena.
#${#array[@]}Número de elementos del array.
[]${array[2]}Acceder al índice 2 del array.

Matiz interesante:
${array[@]} y ${array[*]} parecen iguales, pero no lo son cuando hay espacios:

  • "${array[@]}" → cada elemento es una palabra independiente
  • "${array[*]}" → todo se convierte en una única cadena

Esto afecta a bucles, argumentos, etc.


b) En parámetros posicionales ($1, $2, etc.)

Cuando el script recibe argumentos:

SímboloEjemploSignificado
@"$@"Todos los parámetros, cada uno como una palabra independiente.
*"$*"Todos los parámetros como una sola palabra.
#$#Número total de parámetros recibidos.
0$0Nombre del script.
1,2,3…$1, $2Parám. posicionales: primero, segundo, etc.

Ejemplo visual:

Si ejecutas:





./script.sh uno "dos tres" cuatro
  • "$@"uno dos tres cuatro (3 palabras)
  • "$*"uno dos tres cuatro (1 palabra grande)

c) En globbing (patrones de archivos)

Cuando expandes patrones en el shell:

PatrónEjemploSignificado
**.txtCualquier cadena (0 o más caracteres).
?t?.txtUn solo carácter desconocido.
[]t[aeiou].txtClase de caracteres posibles.
[^ ]t[^a].txtClase negada (cualquiera menos “a”).
{}{jpg,png}Expansión de listas.

Ejemplos rápidos:

  • *.txt coincide con hola.txt, notas.txt, etc.
  • ???.txt coincide con uno.txt pero no con hola.txt.
  • f[oa]r.txt coincide con for.txt y far.txt.

d) En cadenas (longitud y sustitución)

El símbolo # también sirve para medir longitudes:

SímboloEjemploSignificado
#${#var}Longitud de la variable “var”.
%${var%pat}Elimina el patrón más corto por la derecha.
%%${var%%pat}Elimina el patrón más largo por la derecha.
#${var#pat}Elimina el patrón más corto por la izquierda.
##${var##pat}Elimina el patrón más largo por la izquierda.

Ejemplo rápido:





var="archivo.tar.gz"
echo ${var%.*}   # archivo.tar
echo ${var%%.*}  # archivo

Resumen

Contexto@*#
ArraysElementos separadosElementos juntosNúmero de elementos
Parámetros del scriptArgs separadosArgs juntosNúmero de args
GlobbingCualquier cadena
CadenasLongitud

6. Ejemplos Aplicados

Ejemplo 1: Lista de frutas





#!/bin/bash

frutas=("Manzana" "Pera" "Uva")
for fruta in "${frutas[@]}"; do
    echo "Fruta: $fruta"
done

Ejemplo 2: Contar elementos





#!/bin/bash

colores=("Rojo" "Azul" "Verde" "Amarillo")
echo "Hay ${#colores[@]} colores en la lista."

Ejemplo 3: Asociar países con capitales





#!/bin/bash

declare -A capitales
capitales[España]="Madrid"
capitales[Alemania]="Berlín"

for pais in "${!capitales[@]}"; do
    echo "La capital de $pais es ${capitales[$pais]}"
done

Ejercicios propuestos

Ejercicio 1:
Crear un script frutas.sh con un array de frutas y recorrerlo con un for mostrando los elementos.

Ejercicio 2:
Crear un script contar.sh que almacene números del 10 al 50 en un array y muestre cuántos elementos contiene.

Ejercicio 3:
Crear un script capitales.sh con un array asociativo de países → capitales y luego imprimir:





La capital de X es Y

para cada país.

Ejercicio 4:
Crear un script archivos.sh que guarde en un array todos los archivos .txt del directorio actual y los liste.


Soluciones

✅ Ejercicio 1 — frutas.sh

Enunciado:
Crear un script frutas.sh con un array de frutas y recorrerlo con un for mostrando los elementos.

💡 Solución:





#!/bin/bash
# Script: frutas.sh
# Muestra una lista de frutas usando un array

frutas=("Manzana" "Pera" "Naranja" "Plátano" "Kiwi")

echo "Listado de frutas:"
for fruta in "${frutas[@]}"; do
    echo " - $fruta"
done

Salida esperada:





Listado de frutas:
 - Manzana
 - Pera
 - Naranja
 - Plátano
 - Kiwi

✅ Ejercicio 2 — contar.sh

Enunciado:
Crear un script contar.sh que almacene números del 10 al 50 en un array y muestre cuántos elementos contiene.

Puedes interpretarlo de varias formas. Te dejo una solución clara y didáctica.

💡 Solución:





#!/bin/bash
# Script: contar.sh
# Guarda números del 10 al 50 en un array y muestra cuántos hay

numeros=()

for ((i=10; i<=50; i++)); do
    numeros+=("$i")
done

echo "Contenido del array:"
echo "${numeros[@]}"

echo
echo "El array contiene ${#numeros[@]} elementos."

Salida (resumen):





Contenido del array:
10 11 12 ... 50

El array contiene 41 elementos.

✅ Ejercicio 3 — capitales.sh

Enunciado:
Crear un script capitales.sh con un array asociativo de países → capitales y luego imprimir:

La capital de X es Y

para cada país.

💡 Solución:





#!/bin/bash
# Script: capitales.sh
# Usa un array asociativo para países y capitales

declare -A capitales

capitales[España]="Madrid"
capitales[Francia]="París"
capitales[Alemania]="Berlín"
capitales[Italia]="Roma"
capitales[Portugal]="Lisboa"

for pais in "${!capitales[@]}"; do
    echo "La capital de $pais es ${capitales[$pais]}"
done

Salida posible (el orden puede variar, porque los asociativos no garantizan orden):





La capital de España es Madrid
La capital de Francia es París
La capital de Alemania es Berlín
La capital de Italia es Roma
La capital de Portugal es Lisboa

✅ Ejercicio 4 — archivos.sh

Enunciado:
Crear un script archivos.sh que guarde en un array todos los archivos .txt del directorio actual y los liste.

💡 Solución:





#!/bin/bash
# Script: archivos.sh
# Guarda en un array los .txt del directorio actual y los muestra

txt_files=(*.txt)

# Comprobamos si hay alguno
if [ "${#txt_files[@]}" -eq 1 ] && [ "${txt_files[0]}" = "*.txt" ]; then
    echo "No se han encontrado archivos .txt en el directorio actual."
    exit 0
fi

echo "Archivos .txt encontrados:"
for fichero in "${txt_files[@]}"; do
    echo " - $fichero"
done

echo
echo "Total de archivos .txt: ${#txt_files[@]}"

Notas:

  • El truco de comprobar si el único elemento es "*.txt" evita el caso en que no haya .txt y el patrón no se expanda.
  • Esto da pie a hablar de globbing y de nullglob en niveles más avanzados.