Arrays no Shell

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"

Tags: shell Bash Arrays programação scripts

Publicado em 7-4 21:20