Até agora está tudo bem. Mas eu acabei me deparando com uns probleminhas como: Como passar um vetor como argumento para uma função?
Como disse anteriormente, escrever $vetor é escrever o primeiro elemento (índice 0) de vetor. Ou seja, se passarmos o mesmo como $vetor, estaremos usando somente o primeiro elemento.
Ora, pois para passar um determinado vetor como parâmetro de uma função, é preciso "expandir" o seu conteúdo antes de executar a função, para depois passar os seus elementos como argumento. Um exemplo?
#!/bin/bash
## A função abaixo devolve a quantidade de números negativos, positivos e nulos que há num vetor
## Da forma "negativos:neutros:positivos"
function quant
{
local vetor=($@)
local negativo=0
local positivo=0
local neutro=0
local Tamanho=${#vetor[@]}
for ((i=0;i<Tamanho;i++))
do
if ((vetor[i]>0)); then ((positivo++))
elif ((vetor[i]<0)); then ((negativo++))
else ((neutro++)); fi
done
echo "$negativo:$neutro:$positivo"
# Você pode usar o resultado acima para o que quiser, como com o cut, awk, ou sei lá...
}
vetor=(-1 -5 5 6 10 3 8 9 0)
vetor2=(-5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10)
echo "Teste: $(quant ${vetor[@]}))"
quant ${vetor2[@]}
Deixa eu explicar a função acima:
- quant() precisa de um argumento, que é um vetor. Mas o que são passados na verdade são os elementos deste. Cada um deles é reagrupado dentro de "vetor", já dentro da função. Aí é feito o processo de contagem, que é devolvido da forma "negativos:neutros:positivos".
Como é possível perceber, há um tremendo desperdício de processamento quando fazemos essa expansão e juntamos tudo de novo, mas esta foi a solução que eu arranjei. Se alguém aí souber de uma mais elegante ou mais eficiente, estou aceitando sugestões.
Nota: As variáveis vetor, negativo, positivo, neutro e Tamanho são criadas como locais para não terem problemas com as variáveis externas. Só por garantia mesmo ;).
Certo?
Se você executar o script acima, terá a seguinte saída:
Teste: 2:1:6
5:1:10
Outro exemplo:
Invertendo um vetor:
Primeiro escrevemos uma função que realiza a inversão dos elementos de um vetor:
Invert()
{
A=($@)
Tamanho=${#A[@]}
for ((i=0;i<(Tamanho/2);i++))
do
x="${A[$i]}"
A[$i]=${A[((Tamanho-i))]}
A[((Tamanho-i))]="$x"
done
echo ${A[@]}
}
Inicializamos um vetor qualquer:
$ teste=(Zero Um Dois Três Quatro)
E usando a função acima:
$ Invert ${teste[@]}
Quatro Dois Três Um Zero
Nota: Esta saída é proveniente do echo que eu escrevi dentro da função, que é do vetor modificado dentro dela.
Eu não sei porque, mas as funções, do jeito que eu apliquei, não alteram o valor do elemento passado - Isso é o que normalmente chamamos de passagem de parâmetros por valor, ao contrário da passagem por referência, que modifica o valor da variável.
Para mostrar isso, exibimos novamente o conteúdo do vetor teste:
$ echo ${teste[@]}
Zero Um Dois Três Quatro
Mas há um modo um tanto tosco para contornar este problema, que é:
$ teste=(`Invert ${teste[@]}`)
Exibindo o conteúdo de teste:
$ echo ${teste[@]}
Quatro Dois Três Um Zero
Feito.
Strings como argumentos de funções:
Exemplo do uso dos índices de uma string numa função:
Função que recebe uma string e devolve quantas vezes um determinado caractere - Também recebido como parâmetro - aparece nela:
VezCarac()
{
A="$1"
Tamanho=${#A}
cont=0
for ((i=Tamanho-1;i>=0;i--))
do
[ "${A:$i:1}" = "$2" ] && ((cont++))
done
echo $cont
}
Executando:
$ VezCarac "Viva o Linux" i
2
Ou passamos como argumento uma variável que guarda uma string:
$ string="o rato roeu a roupa do rei de roma"
$ VezCarac "$string" r
5
Como foi possível ver, a função VezCarac() varre uma string, caractere por caractere, e se o este for igual ao passado, é incrementado um valor num contador.
Observação: Se você quiser inverter uma string, use o comando rev:
$ string=arara
$ echo $string | rev
arara
Bem, se não acreditou, tente esse outro:
$ echo linux | rev
xunil
Viva o Xunil!!!