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: 33.367 ]

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

Rodando vídeos .rmvb no Linux

Assistindo vídeos no XMMS

Brincando com vetores

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

Mudando o tema dos cursores do mouse no Linux

Leitura recomendada

Conectando-se à Internet via ADSL com PPPoE no OpenBSD

Criando uma ISO bootável do OpenBSD

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

Solução para provedores - Receber aviso no celular quando ocorrer perda de pacote, hosts parados ou pacotes duplicados

Alternância de GPU em notebooks Core-i

  
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