Arrays associativos são uma estrutura de dados poderosa em Bash que permitem associar chaves (strings) a valores, funcionando como um dicionário ou mapa. Diferente dos arrays indexados numericamente, os arrays associativos usam chaves nomeadas para acessar e armazenar dados. Eles foram introduzidos no Bash 4.0 e são extremamente úteis para organizar informações relacionadas de forma legível e eficiente.

Para usar arrays associativos, você precisa declará-los explicitamente com o comando declare -A. Sem essa declaração, o Bash tratará o array como indexado numericamente, o que pode causar erros. Nesta aula, exploraremos a sintaxe, operações comuns e exemplos práticos que demonstram o poder dos arrays associativos em scripts do dia a dia.

declare -A

O comando declare -A é usado para declarar explicitamente um array associativo. A opção -A indica que o array é associativo (mapeamento chave-valor). Sem essa declaração, o Bash assume que o array é indexado numericamente, mesmo que você use chaves com strings.

Exemplo de declaração:

declare -A meu_array

Após a declaração, você pode atribuir valores usando a sintaxe nome_array[chave]=valor ou inicializar o array com uma lista de pares chave-valor entre parênteses:

declare -A cores
cores[vermelho]="#FF0000"
cores[verde]="#00FF00"
cores[azul]="#0000FF"

# Ou inicializar diretamente:
declare -A cores=([vermelho]="#FF0000" [verde]="#00FF00" [azul]="#0000FF")

É importante notar que as chaves são case-sensitive e podem conter espaços, desde que sejam citadas adequadamente. A declaração declare -A é necessária apenas uma vez; depois disso, você pode adicionar novos pares sem redeclarar.

Chave-valor

Em arrays associativos, cada elemento é um par chave-valor. A chave é uma string que identifica unicamente o valor associado. Os valores podem ser strings, números ou até mesmo outros arrays (embora o Bash não suporte aninhamento diretamente).

Para acessar um valor, use ${array[chave]}. Para listar todas as chaves, use ${!array[@]} (o ! antes do nome do array retorna as chaves). Para listar todos os valores, use ${array[@]}.

declare -A capitais
capitais[Brasil]=Brasília
capitais[França]=Paris
capitais[Japão]=Tóquio

echo "A capital do Brasil é ${capitais[Brasil]}"
echo "Todas as capitais: ${capitais[@]}"
echo "Todos os países: ${!capitais[@]}"

Você também pode verificar se uma chave existe com [[ -v array[chave] ]] (a partir do Bash 4.2) ou usando if [[ ${array[chave]+_} ]].

Iteração

Iterar sobre um array associativo pode ser feito de várias formas. A mais comum é usar um loop for sobre as chaves e acessar os valores correspondentes.

declare -A precos=([maçã]=2.50 [banana]=1.20 [laranja]=3.00)

for fruta in "${!precos[@]}"; do
    echo "O preço da $fruta é R$ ${precos[$fruta]}"
done

Se você quiser iterar apenas sobre os valores, use for valor in "${precos[@]}". Para obter o número de elementos, use ${#precos[@]}.

Exemplo de iteração com índice numérico (não recomendado para associativos):

# Isto funciona, mas as chaves são tratadas como índices numéricos
# se o array não foi declarado como associativo.
# Para associativos, use o método acima.

Casos de uso

Arrays associativos são ideais para situações onde você precisa mapear identificadores para dados, como configurações, contagens de frequência, ou tabelas de lookup.

1. Contagem de frequência de palavras:

declare -A freq
texto="gato cachorro gato passaro cachorro gato"
for palavra in $texto; do
    ((freq[$palavra]++))
done
for palavra in "${!freq[@]}"; do
    echo "$palavra: ${freq[$palavra]}"
done

2. Configurações de um programa:

declare -A config
config[nome]="MeuApp"
config[versao]="1.0"
config[debug]=true

echo "Nome: ${config[nome]}, Versão: ${config[versao]}"

3. Mapeamento de códigos de erro para mensagens:

declare -A erros=([404]="Não encontrado" [500]="Erro interno" [403]="Proibido")
codigo=404
echo "Erro $codigo: ${erros[$codigo]:-Desconhecido}"

Arrays associativos também podem ser usados para implementar estruturas de dados mais complexas, como listas de dependências ou caches.

Boas práticas

  • Sempre declare arrays associativos com declare -A antes de usá-los para evitar comportamento inesperado.
  • Use aspas duplas ao redor das chaves e valores para preservar espaços e caracteres especiais.
  • Prefira iterar sobre as chaves (${!array[@]}) para garantir que você acesse todos os elementos corretamente.
  • Evite usar chaves numéricas; se precisar de índices numéricos, use arrays indexados comuns.

Referências

Exercícios

  1. Crie um script que declare um array associativo com nomes de países e suas capitais. Em seguida, imprima a capital de um país específico fornecido como argumento.

    ✓ Resposta:
    #!/bin/bash
    declare -A capitais=([Brasil]=Brasília [França]=Paris [Japão]=Tóquio)
    if [[ -v capitais[$1] ]]; then
        echo "A capital de $1 é ${capitais[$1]}"
    else
        echo "País não encontrado"
    fi
  2. Escreva um script que leia um arquivo de texto (passado como argumento) e conte a frequência de cada palavra usando um array associativo. Imprima as palavras e suas contagens.

    ✓ Resposta:
    #!/bin/bash
    if [[ -z $1 ]]; then
        echo "Uso: $0 arquivo"
        exit 1
    fi
    declare -A freq
    while IFS= read -r linha; do
        for palavra in $linha; do
            ((freq[$palavra]++))
        done
    done < "$1"
    for palavra in "${!freq[@]}"; do
        echo "$palavra: ${freq[$palavra]}"
    done
  3. Crie um array associativo que mapeie códigos de erro HTTP para mensagens. Solicite ao usuário um código e exiba a mensagem correspondente, ou "Código desconhecido" se não existir.

    ✓ Resposta:
    #!/bin/bash
    declare -A erros=([200]="OK" [404]="Não encontrado" [500]="Erro interno")
    read -p "Digite o código HTTP: " codigo
    if [[ -v erros[$codigo] ]]; then
        echo "Código $codigo: ${erros[$codigo]}"
    else
        echo "Código desconhecido"
    fi
  4. Implemente um script que armazene configurações de um aplicativo em um array associativo. As configurações devem ser lidas de um arquivo no formato "chave=valor". Imprima todas as configurações.

    ✓ Resposta:
    #!/bin/bash
    if [[ ! -f $1 ]]; then
        echo "Arquivo não encontrado"
        exit 1
    fi
    declare -A config
    while IFS='=' read -r chave valor; do
        config[$chave]=$valor
    done < "$1"
    for chave in "${!config[@]}"; do
        echo "$chave = ${config[$chave]}"
    done
  5. Escreva um script que use um array associativo para armazenar uma lista de tarefas (chave: descrição, valor: prioridade). Permita ao usuário adicionar tarefas via linha de comando e listar todas as tarefas ordenadas por prioridade (suponha prioridades numéricas).

    ✓ Resposta:
    #!/bin/bash
    declare -A tarefas
    if [[ $1 == "add" && -n $2 && -n $3 ]]; then
        tarefas["$2"]=$3
    elif [[ $1 == "list" ]]; then
        # Ordenar por prioridade (valor)
        for desc in "${!tarefas[@]}"; do
            echo "${tarefas[$desc]} $desc"
        done | sort -n | while read prioridade desc; do
            echo "[$prioridade] $desc"
        done
    else
        echo "Uso: $0 add \"descricao\" prioridade ou $0 list"
    fi