Arrays no Bash: Arrays Indexados e Associativos
O Que Voce Vai Aprender
- A diferenca entre arrays indexados e arrays associativos no bash
- As operacoes fundamentais: declarar, acessar, iterar e adicionar/remover elementos
- Como evitar armadilhas classicas como aspas faltantes em
"${arr[@]}"e arrays esparsos
Resumo Rapido
- Lista ordenada de valores -> array indexado (
arr=(a b c)) - Tabela de busca chave/valor -> array associativo (
declare -A mape obrigatorio) - Sempre use aspas duplas em
"${arr[@]}"ao iterar ou expandir
Pre-requisitos (ambiente alvo)
- Shell: bash 4.0+ (arrays associativos precisam de 4.0+, indices negativos precisam de 4.3+)
sh/dashnao suportam arrays. Use um shebang explicito#!/bin/bash
O que e um array?
Conclusao: Um array armazena multiplos valores em uma unica variavel. O bash tem dois tipos: arrays indexados ordenados e arrays associativos baseados em chaves.
Uma variavel de shell simples armazena um unico valor. Quando voce precisa lidar com varios nomes de arquivos ou usuarios juntos, colocar tudo em uma string separada por espacos quebra assim que um valor contiver um espaco. Um array mantém cada elemento como um valor independente e seguramente entre aspas.
O bash oferece dois tipos de array:
- Array indexado: elementos sao acessados por indices inteiros comecando em
0 - Array associativo: elementos sao buscados por uma chave de string arbitraria (como um hash ou dicionario)
Como usar arrays indexados?
Conclusao: Declare com
arr=(a b c), leia um elemento com${arr[0]}e todos os elementos com"${arr[@]}". Omitir o indice refere-se ao primeiro elemento.
Declarando e atribuindo
# Declarar tudo de uma vez fruits=(apple banana cherry) # Atribuir por indice fruits[3]=durian # Adicionar ao final (operador +=) fruits+=(elderberry fig)
Acessando
echo "${fruits[0]}" # apple (primeiro elemento)
echo "${fruits[-1]}" # fig (ultimo, bash 4.3+)
echo "${fruits[@]}" # todos os elementos, separados por espaco
echo "${#fruits[@]}" # quantidade de elementos (6)
echo "${!fruits[@]}" # todos os indices (0 1 2 3 4 5)Referenciar um array sem indice, como $fruits, e o mesmo que ${fruits[0]} (apenas o primeiro elemento). Cuidado com essa confusao quando voce pretendia usar todos os elementos.
Fatiamento (extraindo um subconjunto)
echo "${fruits[@]:1:2}" # banana cherry (2 elementos a partir do indice 1)Como usar arrays associativos?
Conclusao: Sempre declare um array associativo com
declare -Aantes de usar. Pule isso e o bash o trata como array indexado, colapsando chaves para 0 e corrompendo os dados.
Um array associativo permite usar strings arbitrarias como chaves. A diferenca principal dos arrays indexados e que voce deve declara-lo com declare -A primeiro.
declare -A capital # esquecer isso e ele quebra
capital[japan]=Tokyo
capital[france]=Paris
capital["united states"]=Washington
echo "${capital[japan]}" # Tokyo
echo "${!capital[@]}" # todas as chaves (ordem indefinida)
echo "${capital[@]}" # todos os valores (ordem indefinida)
echo "${#capital[@]}" # quantidade de elementos (3)Sem declare -A, escrever capital[japan]=Tokyo faz o bash avaliar japan aritmeticamente como 0 e atribuir ao indice 0 de um array indexado. Arrays associativos exigem a declaracao.
Arrays associativos nao preservam ordem. Nem a ordem de insercao nem a ordem das chaves e garantida na saida, entao use pipe com sort se precisar de ordenacao.
Como iterar sobre um array?
Conclusao: Itere valores com
for x in "${arr[@]}"e chaves/indices comfor k in "${!arr[@]}". Ambos exigem aspas duplas.
# Processar cada valor por vez
for f in "${fruits[@]}"; do
echo "fruta: $f"
done
# Iterar chaves (associativo) e buscar valores
for country in "${!capital[@]}"; do
echo "$country -> ${capital[$country]}"
doneRemover as aspas, como em for f in ${fruits[@]}, causa divisao de palavras em elementos que contem espacos: um unico elemento apple pie se divide em apple e pie. Sempre use "${arr[@]}" para manter os valores intactos.
Qual e a diferenca entre "${arr[@]}" e "${arr[*]}"?
Conclusao:
[@]expande cada elemento como uma palavra separada;[*]junta todos em uma unica string usando o primeiro caractere de IFS. Use[@]para loops.
| Notacao | Expande para | Uso tipico |
|---|---|---|
"${arr[@]}" |
uma palavra separada por elemento | loops, passagem de args |
"${arr[*]}" |
uma unica string unida por IFS[0] | exibicao, stringify |
arr=(one two three)
printf '[%s]\n' "${arr[@]}" # [one] [two] [three] em linhas separadas
printf '[%s]\n' "${arr[*]}" # [one two three] em uma linha
# Unir com um separador personalizado
IFS=,
echo "${arr[*]}" # one,two,three
unset IFSComo adicionar ou remover elementos?
Conclusao: Adicione com
arr+=(...)e exclua comunset 'arr[2]'. Note que remover de um array indexado o deixa esparso - os indices nao sao renumerados.
arr=(a b c d)
arr+=(e) # adicionar -> a b c d e
unset 'arr[1]' # excluir indice 1 (b)
echo "${arr[@]}" # a c d e
echo "${!arr[@]}" # 0 2 3 4 <- indice 1 esta faltando (nao renumerado)Apos unset, o array nao e mais contíguo (array esparso). A contagem ${#arr[@]} nao corresponde mais ao maior indice, entao qualquer loop assumindo indices 0..N-1 quebra. Reatribua para renumerar:
arr=("${arr[@]}") # reindexar para 0,1,2...Quais sao as armadilhas comuns?
Conclusao: Arrays sao exclusivos do bash, aspas sao obrigatorias, e arrays associativos precisam de declare -A. Perca qualquer um desses e voce tera uma falha classica.
Nao faca isso / facil de errar
- Usar arrays com
#!/bin/sh-> erro de sintaxe nodashetc. Use#!/bin/bash for x in ${arr[@]}(sem aspas) -> elementos com espacos sao divididos- Esquecer
declare -Apara um array associativo -> chaves colapsam para 0 e sobrescrevem umas as outras - Escrever
$arrno lugar dearr[0]-> voce obtem apenas o primeiro elemento, nao todos
Para capturar saida de comandos em um array, mapfile (tambem chamado readarray) le com seguranca linha por linha.
mapfile -t lines < <(ls -1) # cada linha se torna um elemento de lines
echo "${#lines[@]}" # numero de linhasA opcao -t remove a nova linha final de cada linha; sem ela, os elementos mantem um \n.