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.