Criando Arrays, Arrays Multidimensionais e Hashes em BASH Script

Neste artigo, será feita uma descrição breve e direta sobre como usar arrays, arrays multidimensionais e hashes em scripts para BASH. Esta descrição envolve um simples comando que fará toda a diferença.

[ Hits: 13.734 ]

Por: Perfil removido em 26/09/2016


Introdução



Hoje o assunto é sobre como criar arrays (também chamados de vetores) uni e multidimensionais, bem como hashes em BASH Script.

Costumeiramente, usa-se apenas array unidimensional e com índice numérico, que é o mais difundido.

Será apresentada umas das formas de usar uma estrutura multidimensional e também a possibilidade de criação de variáveis hash, tal como em Perl.

Eis aqui um exemplo de um código criador de uma estrutura unidimensional com elementos em índices de 0 a 3:

for ((i=0;i<=3;i++))
do
    array[$i]=$RANDOM
done

Para mostrar os números randômicos atribuídos aos elementos do array, usa-se o código:

for ((i=0;i<=3;i++))
do
    echo 'array['$i']' = ${array[$i]}
done

Para ampliar os poderes da variável que se pretende usar como array multidimensional, usa-se o comando:

declare -A [name[=value] ...]

De acordo com o comando help declare:

-A to make NAMEs associative arrays (if supported) - criar arrays associativos se suportado (tradução livre).

Ou seja, arrays com índices numéricos ou de strings.

E agora, um exemplo de código de como usar um array de duas dimensões:

declare -A matriz

for ((i=0;i<=3;i++))
do
    for ((j=0;j<=4;j++))
    do
        matriz[$i,$j]=$RANDOM
    done
done

Para mostrar os números randômicos atribuídos aos elementos do array multidimensional, pode-se usar:

for ((i=0;i<=3;i++))
do
    for ((j=0;j<=4;j++))
    do
        echo 'matriz['$i','$j']' = ${matriz[$i,$j]}
    done
done

A sintaxe desta variável matriz é a da colocação de índices numéricos separados por vírgulas dentro dos colchetes da declaração da variável. Com isto, podem ser criados arrays com vários índices. Usa uma espécie associativa de índice por causa da vírgula separadora.

Na verdade são hashes, porque a vírgula transforma o índice numa string. É que a sintaxe de índices i,j como [i,j] é legível por humanos de um modo que é interpretado como dois índices numéricos. Tanto é que elementos de arrays com índices [0], [00], [1,1] e [01,01], são todos distintos.

Portanto, em scripts a sintaxe com a string [$i,$j] no único índice comporta-se como dois índices. Ainda há a possibilidade de que cada variável seja uma string, ou que ela possua como valor dados combinados como índices. Afinal, de qualquer modo são strings sendo lidas como índices separados por vírgulas.

Sendo, então, que a declaração da variável matriz poderia ser algo como matriz[2,3,5,7,11,13], de modo que não há limitações de dimensão (desde que haja memória suficiente na máquina, naturalmente), sendo bem flexível o uso na confecção de scripts. Inclusive a declaração não limita a dimensão, ficando a cargo do programador.

O uso de @ ou * no índice da variável, que apresenta os valores de todos os elementos, resultará na exibição dos valores contidos em toda sua estrutura, mas com uma ordem própria, podendo ser sem definição lógica pelos índices ou ordem de inclusão.

Continuando, agora falar-se-á de hashes. Hashes aqui são tidos como arrays de índices alfanuméricos ou strings, que são associativos puros. Como são feitos em linguagens como Perl e Python (em Python, a nomenclatura chama-os de dicionários). C não possui variável tipo hash em sua implementação.

Para ser criado um hash, basta usar o mesmo comando que se usa para a criação de vetores multidimensionais. Exemplificando:

declare -A meuhash

Agora, podem ser feitos hashes com o nome de estrutura sendo "meuhash".

Podendo ser escrito neste hash variáveis tendo índice de string:

meuhash['ano']=2016
meuhash['mes']=08
meuhash['dia']=28

Aspas simples ou duplas são opcionais, mesmo se no índice estiverem espaços em branco.

Para exibir os valores deste hash, pode-se usar o seguinte código:

for i in dia mes ano
do
    echo 'meuhash['$i']' = ${meuhash[$i]}
done

Não há limite para as dimensões de um hash, sendo possível misturar índice de string com índice numérico.

Usar @ ou * também faz com que os valores do hash apareçam numa ordem própria, sem qualquer definição ordenada pelos índices.

Conclusão

Esperou-se aqui explicar e demonstrar com este breve artigo, que é muito simples usar variáveis do tipo array com várias dimensões e também do tipo hash, através do comando declare.

Fontes:
  • help declare
  • man 1 bash

Bem, é isto.
Até mais.

   

Páginas do artigo
   1. Introdução
Outros artigos deste autor

Criando uma aplicação que mostra os processos em execução

Resumo LPI 102: Tópico 108 - Serviços Essenciais do Sistema

Gerenciando redes com Perl e SNMP

Construindo um portscanner TCP com Python

Criando um servidor de impressão para residências e pequenas empresas com Linux

Leitura recomendada

Brincando com vetores

Hdparm - Entendendo seu funcionamento e criando um script para Slackware

Gerar músicas aleatórias com YAD (Modo Gráfico)

Cobrando com o SQUID

KeepAlive para conexão discada (ou não)

  
Comentários
[1] Comentário enviado por removido em 30/09/2016 - 20:38h

Artigo excepcional, parabéns!

Não sabia que era possível criar matrizes multidimensionais no BASH, pensava que fosse uma limitação e que somente as unidimensionais (as quais chamo apenas de "vetores") fossem possíveis de manipular; inclusive tive um problema com isso há um tempo, quando precisei de matrizes reais numa implementação com o BASH;

Mais uma vez parabéns pelo artigo, favoritado!

[2] Comentário enviado por paulo1205 em 02/05/2017 - 11:31h

Bom artigo, Listeiro, mas permita-me fazer algumas correções/sugestões.

Não existe array multidimensional no bash. Você reconhece isso, mas eu acho que seria melhor deixar mais evidente de que o que você propõe é apenas uma simulação.

Sendo uma simulação, seria legal se você pudesse mostrar maneiras de tornar a simulação tão próxima do real quanto possível. Por exemplo, em vez de apenas comentar que o índice “00,00” será diferente do índice “0,0”, mostre um jeito de fazer com que não o seja (por exemplo, fazendo algo como “arr[$((i)),$((j))]”, para simplificar expressões numéricas).

Outro ponto: no seu artigo, você parece supor que arrays associativos são sinônimos de tabelas hash. Eu não achei essa informação na manpage do bash, em seu manual de referência, nem tampouco numa busca no Google. Embora seja muito provável que a implementação seja, sim, por meio de tabelas hash, pode ser temerário afirmar isso se você não tiver uma boa referência ou se não tiver lido o código fonte. Prefira, portanto, referir-se ao recurso pelo nome usado pelo próprio programa e em sua documentação: arrays associativos.

Por fim, vale a pena salientar que os recursos propostos existem apenas a partir do bash 4. O bash 4 não é nenhuma novidade (estamos em 2017), mas sistemas antigos, principalmente os comerciais e com ciclos de atualização lentos (AIX, Solaris, HPUX etc.) podem ter outras versões, que não suportam o recurso.

[3] Comentário enviado por removido em 08/06/2017 - 01:40h

Bem colocado.

É difícil pensar que existam sistemas cujas atualizações sejam mais complicadas, até porque de vez em quando aparecem falhas críticas. Uma delas foi essa: https://en.wikipedia.org/wiki/Shellshock_(software_bug) que falta averiguar da data da criação do artigo e da publicação da solução.

Faz tempo havia saído um exploit para kernel Linux, onde compilava-se um código "ilegível" para mortais e executando-se o binário em seguida tinha-se um prompt hash para root, sem uso aparente de sudo ou su.

Pode ter sido equivocado chamar de hash, mas foi o que mais se aproxima do uso em outras linguagens. Depende da terminalogia. Algumas podem chamar de arrays associativos também. Foi um jeito de explicar para a prática.

De ser novidade em Bash 4 também não percebi. Deveria ter percebido. A man 1 é enorme e a memória já não é tão boa.

Talvez eu tenha deixado passar mais coisas interessantes na construção do artigo. A princípio pensei em deixar como "dica". Daí resolvi detalhar ao máximo e deixar em uma página só. Creio que através dele muitos ficarão sabendo deste recurso, que não é tão óbvio pelo uso do comando declare (bem que poderia ser com declaração direta) e encontrarão novas ideias que não consegui explorar.

----------------------------------------------------------------------------------------------------------------
Nem direita, nem esquerda. Quando se trata de corrupção o Brasil é ambidestro.
(anônimo)

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden

[4] Comentário enviado por xerxeslins em 16/06/2017 - 12:37h

Olá, listeiro! Por acaso você chegou a ver algum e-mail que eu te enviei na quarta passada (dia 14)? Abraço!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts