Postagem em destaque

Criando bot do Telegram em Shell script com ShellBot

Utilizando expansão de arrays

O array é uma estrutura de dados onde são armazenados uma coleção de elementos de tal forma que cada um dos elementos passa a ser intensificado por um índice ou uma chave. O shell apresenta essa estrutura de duas formas, indexada ou por associação. Os elementos podem ser acessados individualmente por sua posição no array ou por seleção de um conjunto de elementos através do recurso de expansão de arrays; onde sua sintaxe é semelhante a expansão de variáveis abordados anteriormente. Os arrays são inicializados em zero, ou seja, o primeiro elemento é indexado com o número '0' (zero).

A declaração da variável pode ser feita indiretamente:

Sintaxe:
$ array[INDICE]=valor

O INDICE é uma expressão aritmética que deve ser um número positivo.

A declaração explícita de uma matriz é realizada utilizando o comando declare.

Sintaxe:
$ declare -a array

A declaração especificando o número do índice será aceita, porém o número de índice será ignorado. Atributos para a matriz pode ser especificado usando o declare ou readonly.

Uma variável array também pode ser criada usando atribuições compostas:



Sintaxe:
$ array=(valor1 valor2 valorN ...)

Cada valor é uma cadeia de caracteres referenciando um elemento dentro do array. O número do índice é opcional. Se fornecido, esse índice é atribuído a ele; Caso contrário, o índice do elemento atribuído é o número do último índice que foi atribuído, mais um. Esse método é suportado pelo declare. Se nenhum índice for fornecido, a indexação começa em zero.

Array associativo

Um array por associação é um variável onde os elementos são referenciados por uma cadeia de caracteres, semelhante ao dicionários da linguagem Python. A criação deste tipo de array só pode ser realizada através do comando declare; Qualquer variável criada indiretamente assume como do tipo indexada, referenciando o valor ao elemento de índice '0' (zero).


Sintaxe:
$ declare -A arrayRef[expressao]=valor

O array pode ser criado utilizando a declaração composta e até mesmo definindo a referência dos elementos.

Sintaxe:
$ array=([exp1]='valor1' [exp2]='valor2' [exp3]='valor3')

Expansão de arrays é um recurso que nos permite manipular um elemento ou uma coleção de elementos dentro de um array.

Expansão
Descrição
${var[@]}
Imprime todos os elementos do array em strings protegidas.
${var[*]}
Imprime todos os elementos do array em uma única expressão.
${var[P]}
Imprime o elemento na posição ‘P’.
${#var[@]}
Imprime o total de elementos do array.
${!var[@]}
Imprime os índices do array.
${var[@]:N}
Imprime todos os elementos a partir da posição ‘N’.
${var[@]:N:M}
Imprime ‘M’ elementos a partir da posição ‘N’.
${var[@]: -N}
Imprime os últimos ‘M’ elementos.
${var[@]: -N:M}
Imprime ‘M’ elementos a partir da última ‘N’ posição.

Exemplos

1. Criando array indexado.

1.1 Criando array indiretamente.
# Array
$ linux[0]='Debian'
$ linux[1]='Slackware'
$ linux[2]='Fedora'

# Imprimindo o valor de todos os elementos.
$ echo ${linux[@]}
Debian Slackware Fedora

Inicia-se o array especificando os índices dos elementos. Os elementos são retornados de acordo com a sua posição no array.

1.2 Criando array composto.
# Array
$ nomes=('Geraldo' 'Francisco' 'Fernando' 'Aline' 'Luciana')

# Imprimindo valores.
$ echo ${nomes[0]}
Geraldo
$ echo ${nomes[2]}
Fernando

# Imprimindo o valor de todos os elementos
$ echo ${nomes[@]}
Geraldo Francisco Fernando Aline Luciana

1.3 Criando array e definindo os índices dos elementos.
# Array
$ clientes=([1]='Luciano' [5]='Leandro' [8]='Jair' [10]='Jaime')

# Imprimindo o valor de todos os elementos.
$ echo ${clientes[@]}
Luciano Leandro Jair Jaime

1.4 Criando array composto e definindo o índice de alguns elementos.
# Array
$ distro=([1]='Debian' 'Slackware' [8]='Ubuntu' 'Elementary' 'Fedora')

# Imprimindo valores.
$ echo ${distro[1]}
Debian
$ echo ${distro[2]}
Slackware
$ echo ${distro[9]}
Elementary
$ echo ${distro[10]}
Fedora

# Imprimindo o valor de todos os elementos.
$ echo ${distro[@]}
Debian Slackware Ubuntu Elementary Fedora

Apesar de retornar na ordem como foi declarados, os elementos não estão em índices subsequentes, ou seja, os itens que não foram indexados recebem o índice do item que o antecede mais 1.

O resultado seria:
[1]='Debian' [2]='Slackware' [8]='Ubuntu' [9]='Elementary' [10]='Fedora'

1.5 Declarando o array e posteriormente atribuindo os valores.
# array
$ declare -a frutas
$ frutas=('laranja' 'maçã' 'laranja')

# Imprimindo o valor de todos os elementos.
$ echo ${frutas[@]}
laranja maçã laranja

1.6 Declarando o array com os elementos.
# array
$ declare -a frutas=('laranja' 'maçã' 'laranja')

# Imprimindo o valor de todos os elementos.
$ echo ${frutas[@]}
laranja maçã laranja

2. Criando um array associativo.

2.1 Declarando array e atribuindo os valores posteriormente.
# array
$ declare -A frutas
$ frutas[laranja]=10
$ frutas[uva]=30
$ frutas[abacaxi]=50

# Imprimindo o valor de cada elemento.
$ echo ${frutas[laranja]}
10
$ echo ${frutas[uva]}
30
$ echo ${frutas[abacaxi]}
50

# Imprimindo o valor de todos os elementos
$ echo ${frutas[@]} 
10 50 30

2.2 Declarando array composto.
# Array
$ declare -A sistema=([desktop]='Windows' [server]='Linux' [mobile]='Android')

# Imprimindo valores
$ echo ${sistema[desktop]}
Windows
$ echo ${sistema[server]}
Linux
$ echo ${sistema[mobile]}
Android

Não é possível criar um array composto sem atribuir o vetor associativo.

Exemplo:
# Erro:
# O elemento 'Windows' não possui um vetor atribuido.
$ declare -A sistema=('Windows' [server]='Linux' [mobile]='Android')

3. Expansão de arrays

3.1 Imprimindo o total de elementos armazenados.
# Array
$ declare -a clientes=('Jaime' 'Maria' 'Fernanda' 'Lucas' 'Alice')

# Imprimindo o total de elementos.
echo ${#clientes[@]}
5

O uso do caractere '@' ou '*', representa todos os elementos contidos no array.

3.2 Imprimindo os índices dos elementos.
# Array
$ declare -a clientes=('Jaime' 'Maria' 'Fernanda' 'Lucas' 'Alice')

# Imprimindo índices
echo ${!clientes[@]}
0 1 2 3 4

Em vez de retornar os valores dos elementos, foram retornados os índices de cada um. Sendo que o primeiro elemento do array é armazenado no vetor de posição '0' (zero).

3.3 Imprimindo todos os elementos a partir do índice 3.
# Array
$ declare -a clientes=('Jaime' 'Maria' 'Fernanda' 'Lucas' 'Alice')

# Imprime os elementos do array a partir do terceiro elemento.
$ echo ${clientes[@]:2}
Fernanda Lucas Alice

3.4 Imprimindo três elementos a partir do índice 2.
# Array
$ declare -a clientes=('Jaime' 'Maria' 'Fernanda' 'Lucas' 'Alice')

# Imprime elementos
$ echo ${clientes[@]:1:3}
Maria Fernanda Lucas

A posição especificada na expansão é o índice do vetor onde o elemento está armazenado. Se o valor do elemento for nulo, é retornado o valor do elemento do índice mais próximo.

3.5 Imprimindo os últimos dois elementos.
# Array
$ declare -a clientes=('Jaime' 'Maria' 'Fernanda' 'Lucas' 'Alice')

# Imprime elementos
$ echo ${clientes[@]: -2}
Lucas Alice

3.6 Imprimindo um elemento a partir do penúltimo elemento.
# Array
$ declare -a clientes=('Jaime' 'Maria' 'Fernanda' 'Lucas' 'Alice')

# Imprime elementos
$ echo ${clientes[@]: -2: 1}
Lucas

Aplicação prática

Criei um script simples para cadastro de clientes que utiliza array's associativos para armazenamento e gerenciamento dos dados.

#!/bin/bash

#---------------------------------------
# Data:        21 de Dezembro de 2016
# Script:      addcliente.sh
# Criado por:  Juliano Santos [SHAMAN]
#---------------------------------------

# Criando um conjunto de array's associativos, onde serão armazenadas as informações do cliente.
declare -A CLIENTE_NOME CLIENTE_IDADE CLIENTE_ENDERECO CLIENTE_TELEFONE

# ADICIONA UM NOVO CLIENTE
Adicionar()
{
 # Limpa as variáveis.
 unset NOME IDADE ENDERECO TELEFONE

 clear
 
 # Exibe o prompt de entrada para inserção dos dados.
 echo $FUNCNAME
 echo
 read -p 'Nome: ' NOME
 read -p 'Idade: ' IDADE
 read -p 'Endereço: ' ENDERECO
 read -p 'Telefone: ' TELEFONE
 
 # Verifica se todos os campos foram preenchidos.
 # Caso haja campos nulos, imprime mensagem de erro e finaliza a função.
 if [ -z "$NOME" -o -z "$IDADE" -o -z "$ENDERECO" -o -z "$TELEFONE" ]; then
  echo -e '\n\033[0;31mTodos os campos são obrigatórios*\033[0m'
  # Sai da função com status 1
  return 1
 # Testa se o cadastro já existe.
 elif [ -n "${CLIENTE_NOME[$NOME]}" ]; then
  echo -e "\n'$NOME': \033[0;32mCliente já cadastrado.\033[0m"
  # Sai da função com status 1
  return 1
 fi
 
 # Atribui o valor de cada variável em um array especifico no vetor associativo
 # com o nome do cliente contido na variável 'NOME'.
 #
 # Exemplo
 #
 # Variáveis
 #
 #  NOME:   Cassio Martins
 # IDADE:   23
 # ENDERECO: Av Mario Ramos
 # TELEFONE: 3465-7865
 #
 # Array's associativo
 #
 # CLIENTE_NOME[Cassio Martins]="Cassio Martins"
 # CLIENTE_IDADE[Cassio Martins]="23"
 # CLIENTE_ENDERECO[Cassio Martins]="Av Mario Ramos"
 # CLIENTE_TELEFONE[Cassio Martins]="3465-7865"
 # 
 CLIENTE_NOME[$NOME]="$NOME"
 CLIENTE_IDADE[$NOME]="$IDADE"
 CLIENTE_ENDERECO[$NOME]="$ENDERECO"
 CLIENTE_TELEFONE[$NOME]="$TELEFONE"

 # Imprime mensagem de sucesso.
 echo
 echo 'CLIENTE ARMAZENADO COM SUCESSO !!!'

 # status 0
 return 0
}

# LISTA TODOS OS CLIENTES CADASTRADOS
Listar()
{
 # Limpa a tela
 clear

 # Cabeçalho
 printf '%25s %5s %40s %10s\n' 'NOME' 'IDADE' 'ENDEREÇO' 'TELEFONE'

 # Lista todos os índices associativos do array 'CLIENTE_NOME'
 for NOME in "${!CLIENTE_NOME[@]}"
 do
  # A variável 'NOME' recebe o índice com o nome do cliente que será utilizado para acessar os demais dados.
  printf '%25s %5s %40s %10s\n' "${CLIENTE_NOME[$NOME]}" "${CLIENTE_IDADE[$NOME]}" "${CLIENTE_ENDERECO[$NOME]}" "${CLIENTE_TELEFONE[$NOME]}"
 done
 
 echo
}

# REMOVE CLIENTE CADASTRADO
Remover()
{
 clear
 
 # Cabeçalho
 echo $FUNCNAME
 echo "Selecione o registro que deseja apagar."
 echo

 # Cria um menu com os índices do array.
 select OPCAO in "${!CLIENTE_NOME[@]}" "Voltar"
 do
  case $OPCAO in
   # Opção voltar
   'Voltar')
    break
    ;;
   '')
    echo 'Opção inválida.'
    ;;
   # Qualquer opção válida
   *)
    # Limpa os valores armazenados no índice associativo de todos os array's.
    unset CLIENTE_NOME["$OPCAO"] CLIENTE_IDADE["$OPCAO"] CLIENTE_ENDERECO["$OPCAO"] CLIENTE_TELEFONE["$OPCAO"]
    
    # Imprime mensagem e finaliza o loop
    echo 'REGISTRO APAGADO COM SUCESSO !!!'
    break
    ;;
  esac
 done
  
}

# MENU PRINCIPAL
while true
do
 clear

 # Cabeçalho
 echo $(basename $0)
 echo 
 # Imprime as opções do menu
 echo '1 - Adicionar cliente'
 echo '2 - Listar clientes'
 echo '3 - Remover cliente'
 echo '4 - Sair'
 
 # Exibe o prompt para a leitura de um único caractere.
 read -n1 -p 'Opcao: ' OPCAO

 # Lê o caractere armazenado e seleciona a opção.
 case $OPCAO in
  1)
   # Chama função
   Adicionar
   ;;
  2)
   # Chama função
   Listar
   ;;
  3)
   # Chama função
   Remover
   ;;
  4)
   # Finaliza o script
   echo -e '\nSaindo...'
   break
   ;;
  *)
   # Opção inválida.
   echo -e '\n\033[0;31mOpcao inválida !!!\033[0m'
   ;;
 esac

 # Pausa entre opções.
 echo '<Pressione qualquer tecla para voltar...>'
 read
done

exit 0
#FIM

Testando...

Menu principal

O nome do cliente é utilizado como índice associativo para armazenamento das informações nos arrays.
Lista os dados armazenados em todos os arrays.

Limpa os dados armazenados nos arrays dentro índice selecionado.
Exibe a lista de clientes após a exclusão.

Verifica se já existe um índice com o nome informado.
Podemos considerar um array como uma estrutura de dados simples, contando com acesso rápido aos elementos onde a forma de acesso é direta, ou seja, especificando o índice do elemento que deseja.

Leia também: Expansão de variáveis

Comentários

  1. Acompanho seu trabalho pelo Facebook. Continue firme

    ResponderExcluir
    Respostas
    1. Obrigado !!! O objetivo é compartilhar conhecimento, manter a qualidade nas postagens e realizar uma abordagem clara a fim de ajudar a galera a entender essa linguagem maravilhosa que é o Shell Script.

      Excluir

Postar um comentário

Contato

Nome

E-mail *

Mensagem *