Arrays associativos no Bash 4+
1. Introdução aos Arrays Associativos
Arrays associativos são estruturas de dados que armazenam pares chave-valor, onde cada chave é única e pode ser uma string arbitrária. Diferentemente dos arrays indexados tradicionais (que usam números inteiros como índices), os arrays associativos funcionam como mapas ou dicionários encontrados em outras linguagens de programação.
A principal diferença entre arrays indexados e associativos está na natureza das chaves:
- Arrays indexados: chaves são números inteiros sequenciais (0, 1, 2, ...)
- Arrays associativos: chaves são strings arbitrárias definidas pelo usuário
Requisito fundamental: Arrays associativos estão disponíveis apenas no Bash versão 4.0 ou superior. Para verificar sua versão do Bash, use:
echo $BASH_VERSION
Se sua versão for anterior à 4.0, será necessário atualizar o Bash para utilizar este recurso.
2. Declaração e Inicialização
Para declarar um array associativo, utilizamos a opção -A (maiúscula) com o comando declare:
declare -A meu_array
A atribuição de valores pode ser feita de duas formas principais:
Atribuição direta:
declare -A usuario
usuario[nome]="João Silva"
usuario[email]="joao@exemplo.com"
usuario[idade]=30
Inicialização com literais:
declare -A config=(
[host]="localhost"
[porta]=8080
[debug]=true
[caminho_log]="/var/log/app"
)
Cuidados importantes:
- Chaves com espaços devem ser colocadas entre aspas: meu_array["chave com espaco"]=valor
- Caracteres especiais como [ e ] precisam ser escapados ou colocados entre aspas
- Valores com espaços também devem ser citados adequadamente
declare -A exemplo
exemplo["nome completo"]="Maria das Dores"
exemplo["valor (R\$)"]=150.50
3. Operações Básicas
Acessando valores:
echo "${usuario[nome]}" # Saída: João Silva
echo "${config[porta]}" # Saída: 8080
Verificando existência de chave:
if [[ -v usuario[email] ]]; then
echo "Chave 'email' existe"
fi
# Alternativa com expansão condicional
if [[ ${config[debug]+existe} ]]; then
echo "Chave 'debug' existe"
fi
Removendo elementos:
unset usuario[idade]
Tamanho do array:
echo "${#usuario[@]}" # Número de pares chave-valor
4. Iteração e Listagem
Percorrendo chaves:
for chave in "${!usuario[@]}"; do
echo "Chave: $chave"
done
Percorrendo valores:
for valor in "${usuario[@]}"; do
echo "Valor: $valor"
done
Percorrendo pares chave-valor simultaneamente:
for chave in "${!usuario[@]}"; do
echo "$chave => ${usuario[$chave]}"
done
Uso com printf para formatação:
printf "%-20s => %s\n" "chave" "valor"
for chave in "${!config[@]}"; do
printf "%-20s => %s\n" "$chave" "${config[$chave]}"
done
5. Manipulação Avançada
Copiando arrays associativos:
declare -A copia
for chave in "${!original[@]}"; do
copia["$chave"]="${original[$chave]}"
done
Mesclando dois arrays associativos:
declare -A mesclado
for chave in "${!arr1[@]}" "${!arr2[@]}"; do
if [[ -v arr2[$chave] ]]; then
mesclado["$chave"]="${arr2[$chave]}"
else
mesclado["$chave"]="${arr1[$chave]}"
fi
done
Ordenação de chaves ou valores:
# Ordenar chaves
for chave in $(printf '%s\n' "${!config[@]}" | sort); do
echo "$chave => ${config[$chave]}"
done
# Ordenar por valores
for valor in $(printf '%s\n' "${config[@]}" | sort); do
for chave in "${!config[@]}"; do
[[ "${config[$chave]}" == "$valor" ]] && echo "$chave => $valor"
done
done
Uso de variáveis como chaves dinâmicas:
declare -A dados
chave_dinamica="usuario_$(date +%s)"
dados["$chave_dinamica"]="valor dinâmico"
6. Aplicações Práticas
Contagem de frequência de palavras:
declare -A frequencia
texto="gato cachorro gato passaro cachorro gato"
for palavra in $texto; do
((frequencia[$palavra]++))
done
for palavra in "${!frequencia[@]}"; do
echo "$palavra: ${frequencia[$palavra]}"
done
Mapeamento de configurações (arquivo .conf):
declare -A config_app
while IFS='=' read -r chave valor; do
[[ -z "$chave" || "$chave" =~ ^# ]] && continue
config_app["$chave"]="$valor"
done < "app.conf"
Cache de resultados de comandos:
declare -A cache_comandos
executar_com_cache() {
local cmd="$1"
if [[ -v cache_comandos[$cmd] ]]; then
echo "Usando cache"
echo "${cache_comandos[$cmd]}"
else
echo "Executando comando"
cache_comandos["$cmd"]=$(eval "$cmd" 2>/dev/null)
echo "${cache_comandos[$cmd]}"
fi
}
Tabelas de lookup para substituição de texto:
declare -A substituicoes=(
[":user:"]="joaosilva"
[":date:"]="$(date +%Y-%m-%d)"
[":version:"]="2.1.0"
)
template="Usuário: :user:, Data: :date:, Versão: :version:"
for chave in "${!substituicoes[@]}"; do
template="${template//$chave/${substituicoes[$chave]}}"
done
echo "$template"
7. Limitações e Boas Práticas
Limitações importantes:
- Chaves devem ser strings (não é possível usar números como chaves sem convertê-los para string)
- Não há ordenação garantida dos elementos (a ordem de iteração é imprevisível)
- Arrays associativos não podem ser exportados para subshells diretamente
Exportação e passagem para funções:
# Passagem para função (por referência)
processa_array() {
local -n arr_ref=$1
for chave in "${!arr_ref[@]}"; do
echo "$chave => ${arr_ref[$chave]}"
done
}
declare -A meu_arr=([a]=1 [b]=2)
processa_array meu_arr
Diferenças entre ${!array[@]} e ${!array[*]}:
- ${!array[@]}: Expande para uma lista de chaves, preservando palavras com espaços
- ${!array[*]}: Expande para uma única string com todas as chaves
Dicas de desempenho e legibilidade:
- Use nomes descritivos para seus arrays associativos
- Prefira declare -A explícito em vez de declaração implícita
- Utilize [[ -v array[chave] ]] para verificar existência (mais rápido que ${array[chave]+existe})
- Para arrays muito grandes, considere usar arquivos temporários ou bancos de dados
# Boa prática: sempre declarar explicitamente
declare -A config_servidor
# Evitar: uso implícito (pode causar erros)
config_servidor[host]="localhost" # Funciona, mas menos seguro
Referências
- GNU Bash Manual - Arrays — Documentação oficial sobre arrays no Bash, incluindo arrays associativos
- Advanced Bash-Scripting Guide: Arrays — Guia avançado com exemplos detalhados de uso de arrays associativos
- Bash Hackers Wiki - Associative Arrays — Wiki técnica com explicações aprofundadas sobre sintaxe e comportamento
- ShellCheck - SC2191 — Ferramenta de análise estática com dicas específicas para arrays associativos
- Linuxize - Bash Associative Arrays — Tutorial prático com exemplos de aplicações reais
- How To Geek - How to Use Associative Arrays in Bash — Guia introdutório com exemplos passo a passo
- Stack Overflow - Bash associative array sorting — Discussões e soluções da comunidade sobre ordenação de arrays associativos