Arrays em Shell são variáveis especiais que armazenam coleções de dados, permitindo operações individuais em cada elemento. Existem dois tipos principais:
- Arrays Indexados: Utilizam inteiros como índices (subscritos dos elementos).
- Arrays Associativos: Permitem usar strings como índices (subscritos dos elementos).
No Bash atual, são suportados apenas arrays unidimensionais indexados e associativos, sem limitação de tamanho.
Embora o Shell não ofereça uma variedade de tipos de dados como linguagens como Java ou C, os arrays são uma ferramenta pdoerosa para operações como cálculo de comprimento, elementos de percorrida, fatiamento, substituição e exclusão.
Diferente de Java/C, os arrays em Shell são unidimensionais. Os elementos podem ter qualquer tamanho e não há necessidade de definir o número de elementos antecipadamente. Os índices começam em 0, similar a Java/C/Python.
Arrays indexados são definidos usando parênteses, com elementos separados por espaços.
Observações:
- Os elementos devem ser separados por espaços.
- Os índices podem ser definidos fora de ordem.
- Strings podem ser facilmente convertidas em arrays.
Formas de definição:
Método 1: Atribuição individual
# Definindo um array vazio
nomes=()
# Atribuindo valores individuais
nomes[0]="João"
nomes[1]="Maria"
nomes[2]="Pedro"
Método 2: Atribuição múltipla
# Atribuindo múltiplos valores de uma vez
frutas=(maçã banana laranja uva)
# Atribuindo resultados de comandos
linhas=$(cat /etc/hosts)
arquivo_hosts=($linhas)
# Atribuição com índices personalizados
numeros=(1 2 3 [10]="dez")
Exemplos práticos
#!/bin/bash
# Atribuição múltipla
frutas=("maçã" "banana" "laranja" "uva")
# Atribuição individual
cores[0]="vermelho"
cores[1]="azul"
cores[5]="verde"
# Resultados de comandos
processos=($(ps aux | awk '{print $1}'))
# Atribuição personalizada
valores=(1 2 3 "olá mundo" [8]="ha")
Arrays associativos devem ser declarados explicitamente usando o comando declare.
Comando declare
O comando declare define atributos de variáveis:
| Opção | Descrição |
|---|---|
| -i | Define como inteiro |
| -a | Define como array |
| -x | Define como variável global/ambiente |
| -r | Define como somente leitura |
Definindo arrays associativos
# Declarando array associativo
declare -A info_usuario
# Atribuindo valores
info_usuario[nome]="devops"
info_usuario[idade]=30
# Ou de forma direta
declare -A info_usuario=([nome]="devops" [idade]=30)
Nota: Arrays associativos definidos fora de funções são globais; dentro de funções são locais.
Gerenciamento de arrays associativos
Declaração
# Declarando arrays associativos
declare -A array_ass1
declare -A array_ass2
Atribuição
Atribuição individual
# Nome_array[índice]=valor
array_ass1[linux]="um"
array_ass1[java]="dois"
array_ass1[php]="três"
Atribuição múltipla
array_ass2=([nome1]="harry" [nome2]="jack" [nome3]="amy" [nome4]="Miss zhang")
Visualização
# Visualizando arrays associativos
declare -A
Acessando valores
# Acessando valor por índice
echo ${array_ass1[linux]} # Saída: um
echo ${array_ass1[php]} # Saída: três
# Acessando todos os valores
echo ${array_ass1[*]} # Saída: três dois um
# Acessando todos os índices
echo ${!array_ass1[*]} # Saída: php java linux
# Contando elementos
echo ${#array_ass1[*]} # Saída: 3
echo ${#array_ass2[*]} # Saída: 4
Acesso aos elementos: ${nome_array[índice]}
Índices: Por padrão, os índices indicam a posição dos elementos no array, começando em 0 (exceto para arrays associativos).
Exemplo:
array=("var1" "var2" "var3" "var4")
Elementos: var1 var2 var3 var4
Índices: 0 1 2 3
Para acessar var2: ${array[1]}
Várias formas de acesso a arrays
${array[i]} # i representa o índice do elemento
# Usando @ ou * para obter todos os elementos:
echo ${array[0]} # Obtém o primeiro elemento
echo ${array[*]} # Obtém todos os elementos
echo ${#array[*]} # Obtém o número total de elementos
echo ${!array[@]} # Obtém os índices dos elementos
echo ${array[@]:1:2} # Obtém um intervalo específico de elementos
Exemplo prático
#!/bin/bash
# Atribuição múltipla
frutas=("maçã" "banana" "laranja" "uva")
# Atribuição individual
cores[0]="vermelho"
cores[1]="azul"
cores[5]="verde"
# Resultados de comandos
linhas=$(cat /etc/passwd)
arquivo_passwd=($linhas)
# Atribuição personalizada
valores=(1 2 3 "olá mundo" [8]="ha")
# Acessando valores
echo ${frutas[2]} # Saída: laranja
echo ${cores[1]} # Saída: azul
echo ${arquivo_passwd[0]} # Saída: root:x:0:0:root:/root:/bin/bash
echo ${valores[8]} # Saída: ha
# Acessando todos os elementos de cores
echo ${cores[*]} # Saída: vermelho azul verde
# Contando elementos de cores
echo ${#cores[*]} # Saída: 3
# Acessando índices de cores
echo ${!cores[@]} # Saída: 0 1 5
# Acessando intervalo específico
echo ${frutas[*]:1:2} # Saída: banana laranja
Fatiamento de arrays
Sintaxe: ${ARRAY[@]:offset:quantidade}
- Offset: Posição inicial (0 para esquerda, -1 para direita).
- Quantidade: Número de elementos a serem recuperados.
Exemplos:
# Offset positivo (da esquerda para direita)
${ARRAY[@]:2:3} # Começa do índice 2, pega 3 elementos
# Offset negativo (da direita para esquerda)
${ARRAY[@]: -3:2} # Começa do 3º elemento da direita, pega 2 elementos
# Sem quantidade especificada
${ARRAY[@]:2} # Começa do índice 2 até o final
Operações comuns
Acessando valores
echo ${array[0]} # Primeiro elemento
echo ${array[-1]} # Último elemento
echo ${array[*]} # Todos os elementos
echo ${#array[*]} # Comprimento do array
echo ${!array[@]} # Todos os índices
Exclusão de elementos e arrays
unset array[2] # Remove o elemento no índice 2
unset array # Remove todo o array
Percorrendo arrays
Método 1: Acesso direto
for elemento in "${array[@]}"
do
echo $elemento
done
Método 2: Por índice
for indice in "${!array[@]}"
do
echo ${array[$indice]}
done
Método 3: Estilo C
for ((i=0; i<${#array[@]}; i++))
do
echo ${array[$i]}
done
Ao acessar todos os elementos do array com echo, $* e $@ têm o mesmo comportamento.
No entanto, dentro de loops há diferenças:
${array[*]}trata todos os elementos como uma única string.${array[@]}trata cada elemento como uma string separada.
Recomendação: Use ${array[@]} para manter a separação dos elementos.
Convertendo string separada por dois pontos em array
string="12:34:56"
array=(${string/:/ })
Leitura de array com read
read -a array <<< "elemento1 elemento2 elemento3"
Definindo IFS para leitura de arquivo
IFS=$'\n'
linhas=($(cat arquivo.txt))
Objetivo: Exibir os valores de carga média da CPU para 1, 5 e 15 minutos.
Estratégia:
- Coletar os valores de carga da CPU.
- Armazenar em um array.
- Exibir os valores correspondentes.
Implementação:
#!/bin/bash
# 1. Coletando valores de carga
carga_cpu=($(uptime | tr -s " " | cut -d " " -f9-11 | tr "," " "))
# 2. Exibindo valores
echo "Carga média da CPU (1 min): ${carga_cpu[0]}"
echo "Carga média da CPU (5 min): ${carga_cpu[1]}"
echo "Carga média da CPU (15 min): ${carga_cpu[2]}"
Comprimento do array
${array_name[@]} ou ${array_name[*]} exibem todos os elementos.
${#array_name[@]} ou ${#array_name[*]} retornam o comprimento.
Índices do array
s="A,B,C,D"
a=($(echo $s | tr ',' ' '))
echo ${!a[@]} # Saída: 0 1 2 3
Exclusão de elementos
a=("A" "B" "C" "D")
unset a[2] # Remove o elemento no índice 2
echo ${a[@]} # Saída: A B D
Percorrendo arrays
Método 1 (estilo C):
for ((i=0; i<${#array[@]}; i++))
do
echo ${array[i]}
done
Método 2 (estilo Python):
for elemento in "${array[@]}"
do
echo $elemento
done
Recomendação: O segundo método é mais legível e eficiente.
Atribuição e adição
Atribuição:
# Reatribuindo elemento existente
array[0]="novo_valor"
# Adicionando elemento novo
array[${#array[@]}]="novo_elemento"
Fatiamento de arrays
Formato geral: ${array[@]:posição_inicial:quantidade}
- Se a quantidade não for especificada, pega até o final.
- Posição inicial pode ser negativa (deve ter espaço antes do sinal).
- Quantidade não pode ser negativa.
Substituição em arrays
${array[@]/x/y} # Substituição mínima (uma vez por elemento)
${array[@]//x/y} # Substituição máxima (várias vezes por elemento)
${array[@]/x/} # Remoção mínima (um elemento por vez)
${array[@]//x/} # Remoção máxima (múltiplos elementos)
${array[@]/#x/y} # Substituição do início da string
${array[@]/%x/y} # Substituição do fim da string
Exclusão de padrões
# # - correspondência mais curta da esquerda para direita
## - correspondência mais longa da esquerda para direita
# % - correspondência mais curta da direita para esquerda
# %% - correspondência mais longa da direita para esquerda
Exemplo 1: Exibindo IPs do ifconfig
#!/bin/bash
# Obtém IPs locais do ifconfig
ips=($(ifconfig | grep "inet " | awk '{print $2}'))
# Exibe cada IP
for ip in "${ips[@]}"
do
echo $ip
done
Exemplo 2: Simulando operações de pilha
#!/bin/bash
# Inicializa pilha
declare -a pilha
# Função push (empilhar)
push() {
pilha+=("$1")
}
# Função pop (desempilhar)
pop() {
local elemento=${pilha[-1]}
unset pilha[-1]
echo $elemento
}
# Exemplo de uso
push "elemento1"
push "elemento2"
echo "Desempilhado: $(pop)"
echo "Desempilhado: $(pop)"
Exemplo 3: Números aleatórios não repetidos
#!/bin/bash
# Gera 10 números aleatórios não repetidos entre 1 e 10
declare -a numeros
declare -a usados
for ((i=0; i<10; i++)); do
while true; do
num=$((RANDOM % 10 + 1))
if [[ ! " ${usados[@]} " =~ " $num " ]]; then
numeros[i]=$num
usados+=($num)
break
fi
done
done
echo "Números aleatórios: ${numeros[@]}"
Exemplo 4: String para array e processamento
#!/bin/bash
# Converte string em array
texto="Esta é uma frase de teste"
palavras=($texto)
# Processa cada palavra
for palavra in "${palavras[@]}"; do
echo "Palavra: $palavra, Comprimento: ${#palavra}"
done
Exemplo 5: Leitura de array com read
#!/bin/bash
echo "Digite várias palavras separadas por espaços:"
read -a palavras
echo "Você digitou: ${palavras[@]}"
Exemplo 6: Verifiacção de elemento em array
#!/bin/bash
# Array de exemplo
cores=("vermelho" "azul" "verde")
# Verifica se uma cor existe no array
verifica_cor() {
local cor=$1
for c in "${cores[@]}"; do
if [[ "$c" == "$cor" ]]; then
echo "YES"
return 0
fi
done
echo "NO"
}
# Exemplo de uso
echo "verde está no array? $(verifica_cor "verde")"
echo "amarelo está no array? $(verifica_cor "amarelo")"
Exemplo 7: Ordenação de array (Bubble Sort)
#!/bin/bash
# Array de exemplo
numeros=(64 34 25 12 22 11 90)
# Bubble Sort
tamanho=${#numeros[@]}
for ((i=0; i<tamanho-1 do="" for="" i="" if="" j=""> ${numeros[j+1]} )); then
# Troca elementos
temp=${numeros[j]}
numeros[j]=${numeros[j+1]}
numeros[j+1]=$temp
fi
done
done
echo "Array ordenado: ${numeros[@]}"
</tamanho-1>
Exemplo 8: Obtendo nomes de usuários do /etc/passwd
#!/bin/bash
# Extrai nomes de usuários do /etc/passwd
usuarios=($(cut -d: -f1 /etc/passwd))
echo "Usuários do sistema: ${usuarios[@]}"
Exemplo 9: Quadrados de números
#!/bin/bash
# Gera array com quadrados de 1 a 8
declare -a quadrados
for ((i=1; i<=8; i++)); do
quadrados[i]=$((i * i))
done
echo "Quadrados: ${quadrados[@]}"
Exemplo 10: Configurando variáveis de ambiente com arrays
#!/bin/bash
# Configura SHELLS com múltiplos shells
declare -a SHELLS=("/bin/bash" "/bin/sh" "/bin/zsh")
export SHELLS
Exemplo 11: Leitura de arquivo com IFS personalizado
#!/bin/bash
# Lê arquivo linha por linha
IFS=$'\n'
linhas=($(cat /etc/passwd))
for linha in "${linhas[@]}"; do
echo "Linha: $linha"
done
Exemplo 12: Simulação de array com eval
#!/bin/bash
# Simula array usando eval
declare -a sim_array
sim_array=("valor1" "valor2" "valor3")
# Acessando elementos
for i in "${!sim_array[@]}"; do
echo "Elemento $i: ${sim_array[i]}"
done
Exemplo 13: Ordenação com array (Bubble Sort)
Implementação completa do algoritmo Bubble Sort usando arrays.
#!/bin/bash
# Array de exemplo
numeros=(64 34 25 12 22 11 90)
# Bubble Sort
tamanho=${#numeros[@]}
for ((i=0; i<tamanho-1 do="" for="" i="" if="" j=""> ${numeros[j+1]} )); then
# Troca elementos
temp=${numeros[j]}
numeros[j]=${numeros[j+1]}
numeros[j+1]=$temp
fi
done
done
echo "Array ordenado: ${numeros[@]}"
</tamanho-1>
Exemplo 14: Encontrando valor máximo em array
#!/bin/bash
# Array de exemplo
valores=(10 25 7 42 18 33 5)
# Inicializa máximo com o primeiro elemento
maximo=${valores[0]}
# Percorre array para encontrar máximo
for valor in "${valores[@]}"; do
if (( valor > maximo )); then
maximo=$valor
fi
done
echo "Valor máximo: $maximo"