Brincando com vetores - complemento

Este é uma espécie de "complemento" do meu artigo anterior, sobre vetores. Neste eu apresento recursos como: utilizar a variável IFS com vetores, usar variáveis readonly, além de uma melhoria no método para passar um vetor como argumento para uma função. Espero que gostem.

[ Hits: 32.959 ]

Por: Leandro Santiago em 26/03/2007 | Blog: http://leandrosan.wordpress.com


Algumas funções que podem ser úteis



Essa é uma função que eu achei muito útil, e tem a função de criar um backup de uma variável:

$ BackupVar()
{
    eval $1[1]=\"\$$1\"
}


Como ela funciona?
É assim: de vez em quando precisamos modificar uma variável, mas restaura-la depois. Como disse no artigo anterior, uma variável comum também é um vetor, mas com somente o primeiro elemento acessado. Essa função cria uma cópia do conteúdo da variável na própria variável!

Exemplo:

$ variavel="O rato"
$ BackupVar variavel


Posso modificar a variável à vontade

$ variavel="O gato"
$ echo $variavel

O gato

Beleza.

Agora uma função que restaura o valor anterior ao "backup":

$ RestoreVar()
{
    eval $1='"${'$1'[1]}"'
    eval unset $1[1]
}


Já temos a variável variavel com o conteúdo "O gato". Restaurando ela ao valor original:

$ RestoreVar variavel
$ echo $variavel

O rato

Isso evita aquele recurso que utilizamos de usar uma variável de backup, tipo:

$ variavel_backup=$variavel

E já viu, achar nome para tanta variável pode complicar depois...

OBS: Você poderia reclamar desse negócio de usar tanta função, pois elas deixam o programa mais lento, pois o processador para a execução do programa e executa a função, etc. Não sei se há um recurso como o inline do c++, mas numa linguagem em alto nível como o shell script, não adianta ficar pensando muito em velocidade na execução, senão a gente pira! (Daqui há uns anos eu aprendo assembly e talvez pense em velocidade...).

Continuando...

No artigo anterior, eu comentei que o bash só aceita vetores unidimensionais. Disse também que não é impossível implementar, por assim dizer, uma espécie de "suporte" à vetores bidimensionais, certo?

Pois que eu tentei aqui uma destas implementações, que mostrarei adiante. Mas acontece que ela possui muitas restrições. Uma delas é que o valor atribuído não pode conter caracteres underline (_) e acento circunflexo (^), pois estes caracteres são usados internamente nas funções.

Outra limitação é a sintaxe dos comandos. Como tudo será baseado em funções, é necessário que chamemos essa função, seguida dos argumentos, que são: nomedovetor posiçãoX posiçãoY valor.

Por exemplo, Se quisermos atribuir o valor elemteste à posição Array[0,1] da matriz Array, fazemos:

$ SetElemento Array 0 1 elemteste

Confesso que não é muito prático, mas o que eu peço é: abstraia! ;)

Outra limitação neste caso é: Os elementos inseridos na "coordenada Y" devem ser inseridos ordinalmente. Explicando: não é possível inserir o elemento [1,2] antes de inserir o [1,1], assim como que não é possível inserir este sem que haja um [1,0].

Não é possível usar índices negativos - estes começam sempre em zero (0).

Mais uma é o fato de não podermos usar comandos que envolvem aritmética com esses vetores, pois tudo será feito à base de funções. Mas você pode, por exemplo, atribuir o valor de uma posição na matriz à uma variável, ou sei lá o que...

Para exibir um elemento na posição [5,3] de um vetor Array, basta:

$ EchoElemento Array 5 3

Continua não sendo muito prático, mas pra mim está de bom tamanho (por enquanto).

OBS: Deixo claro que não temos efetivamente um vetor de duas dimensões em shell. Se você tentar exibir o conteúdo de um destes vetores bidimensionais, verá que ele é um vetor comum. Nós só tratamos ele como tendo duas.

Ah, é claro, aqui vão as funções que realizam estes processos:

$ SetY() # Lista Posição Valor
{
    local IFS=^
    local VetorDirY=($1)
    VetorDirY[$2]="$3"
    echo ${VetorDirY[@]} | tr " " "^"
}


$ EchoElemento() # NomeVetor posX posY
{
    eval local ElemComEsp=\`echo '${'$1'['$2']} | cut -f'"$(($3+1))"' -d^ | tr "_" " "'\`
    echo $ElemComEsp
}


$ SetElemento() # NomeVetor posX posY valor
{
    local ElemSemEsp=`echo $4 | tr " " "_"`
    eval $1[$2]=\`SetY '${'$1'['$2']}' $3 $ElemSemEsp\`
}


Desculpem por não comentar bem as funções, mas acho que está claro o que cada comando faz.

Página anterior     Próxima página

Páginas do artigo
   1. A variável IFS
   2. Vetores read-only
   3. Passando valores por referência em funções
   4. Algumas funções que podem ser úteis
   5. Conclusão
Outros artigos deste autor

Recursos avançados do bash que você não aprende na escola

Ogle: O player de DVD

Instalando um ambiente leve e funcional em computadores antigos

Alguns recursos do BASH para você utilizar em seus programas

Brincando com vetores

Leitura recomendada

Convertendo TXT ou HTML em OGG

Automatização de backup

Fazendo backup do seu MySQL com API do Dropbox

Terminal Didático - Shell Script via WEB (PHP + Bootstrap)

Script "apagador de linhas"

  
Comentários
[1] Comentário enviado por removido em 27/03/2007 - 17:07h

Muito bom meu caro tenchi ;)

[2] Comentário enviado por fernandoamador em 08/04/2007 - 23:55h

Ótimo artgo...


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts