Um array mantêm uma série de elementos de dados, geralmente do mesmo tamanho e tipo de dados. Elementos individuais são acessados por sua posição no array, cuja posição é dada por um índice (geralmente, dentro de uma sequência de números inteiros). É conhecido como vetor, caso seja uni-dimensional, ou matriz, para um array bi-dimensional. Vejamos alguns pontos importantes e exemplos de uso de vetores em shell script (utilizado interpretador de comandos compatível com o sh, que é o bash).
Em um vetor, os elementos são separados por um espaço. Neste caso, o espaço não é um caractere (‘ ‘), e sim um separador dos elementos. Vejamos esse exemplo de vetor e o acesso às diferentes posições e elementos do vetor:
aeroportos=("cgh" "gru" "bsb" "sdu")
Nesse caso, aeroportos[0] é “cgh”, aeroportos[1] é “gru” e assim por diante. Para imprimir na tela o conteúdo de uma posição do vetor, temos:
$ echo ${aeroportos[1]}
Para exibir todos os elementos de um vetor, devemos usar a mesma estrutura, mas no lugar do índice, utilizar arroba [@] ou asterisco [*]. Veja o exemplo a seguir de uma rotina para copiar os dados de computadores em diferentes aeroportos para um computador de backup, onde cada diretório possui como nome a data do dia na forma ANO-MES-DIA:
#!/bin/bash #crontab -e: [minutos] [horas] [dias do mês] [mês] [dias da semana] [usuário] [comando] #59 23 * * * receiver ./transmite.sh data=`date +%F` ano=`date +%Y` #IPs dos aeroportos estao definidos em /home/locator/.ssh/config na máquina com o script aeroportos=("cgh" "gru" "bsb" "sdu") aeroporto=("Congonhas" "Guarulhos" "Brasilia" "Santos_Dumont") LIMITE=`echo ${aeroportos[*]} | wc -w` for ((i=0; i <= $LIMITE-1 ; i++)) do # Mandar pra BACKUP no PC "ip" sshpass -p "SENHA" rsync -azvr --progress user@${aeroportos[$i]}:/home/dados/$data user@ip:/dados/${aeroporto[$i]}/BACKUP/$ano done
Para exibir o intervalo fechado de i até i+k, use:
$ echo ${vetor[@]:$i:((k+1))}
Outro exemplo, que conta o número de arquivos de diretórios (listados em cada linha do arquivo lista_dias.txt) e imprime o total em linhas do arquivo controle_aeroporto.txt
#!/bin/bash # Listar diretórios/arquivos que faltam comparando com total de arquivos aeroportos=("cgh" "gru" "bsb" "sdu") for x in "${aeroportos[@]}"; do cd /dados/$x/BACKUP for i in $(cat ../../lista_dias.txt); do total_arq=0 linha_dir="" total_arq="" data=(`echo $i | tr "-" "\n"`) ano=${data[0]} linha_dir=`ls $ano | grep $i` # Se o diretorio existir... if [ -n $linha_dir ]; then total_arq=`ls $ano/$i | wc -l` echo $total_arq else echo "0" fi done > /dados/controle_$x.txt 2> /dev/null done
Para copiar o vetor original para uma nova variável, não basta fazer da mesma forma que é feito com uma variável. Além de indicar que deseja copiar todos os seus elementos, deve colocar novamente parênteses para transformar o conteúdo em elementos de um novo vetor:
copy=(${original[*]})
Se não fizer isso, todos os elementos do vetor original viram uma única posição em uma variável. Uma discussão com exemplos é realizada no blog do Ahmed Amayem.
Para um script receber um vetor como argumento, ele deve ser inserido na chamada dessa rotina da seguinte forma:
$ teste.sh $arg1 "Sub" $arg3 $arg4 "${vetorum[@]}" "${vetordois[@]}"
Note que foram passados quatro variáveis e dois vetores. Para o shell script receber esses valores, não será possível receber um vetor como uma variável só. Assim, a ideia é tratar TODOS os elementos (incluindo os elementos dos vetores) como sendo um único array e depois separar as variáveis fora dos vetores. Veja o exemplo:
#!/bin/bash ## Script para receber array como argumento # Recebe todos os argumentos como um único array array=( "$@" ) tamanho=${#array[@]} inicio=4 # Número de elementos fora dos vetores # Guardar os primeiros elementos como variáveis hist_fim=${array[0]} tipo=${array[1]} flag_mes=${array[2]} flag_ophen=${array[3]} # Percorrer vetor para trabalhar variáveis for ((i=$inicio; i <= $tamanho-1 ; i++)); do elemento=${array[$i]} echo $elemento done
Por último, um exemplo com uns vetores enormes de mês, dia e hora (a cada 15 minutos). Seu objetivo é descompactar arquivos “.tar.gz” (ou “.tar.bz2”) e unir os conteúdos em outro arquivo final (também apaga diretório que não será mais usado e compacta arquivo):
#!/bin/bash ano=2009 mes=("01" "02" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12") dia=("01" "02" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30" "31") hora=("0000" "0015" "0030" "0045" "0100" "0115" "0130" "0145" "0200" "0215" "0230" "0245" "0300" "0315" "0330" "0345" "0400" "0415" "0430" "0445" "0500" "0515" "0530" "0545" "0600" "0615" "0630" "0645" "0700" "0715" "0730" "0745" "0800" "0815" "0830" "0845" "0900" "0915" "0930" "0945" "1000" "1015" "1030" "1045" "1100" "1115" "1130" "1145" "1200" "1215" "1230" "1245" "1300" "1315" "1330" "1345" "1400" "1415" "1430" "1445" "1500" "1515" "1530" "1545" "1600" "1615" "1630" "1645" "1700" "1715" "1730" "1745" "1800" "1815" "1830" "1845" "1900" "1915" "1930" "1945" "2000" "2015" "2030" "2045" "2100" "2115" "2130" "2145" "2200" "2215" "2230" "2245" "2300" "2315" "2330" "2345") # para cada arquivo tar for ((m=3; m <= 11 ; m++)) do arquivotar="$ano-"${mes[$m]}"_arquivos.tar.gz" #arquivotar="$ano-"${mes[$m]}"_arquivos.tar.bz2" # se o arquivo existir, descompactar if test -f $arquivotar then ndir="$ano-"${mes[$m]}"" mkdir $ndir tar -zxvf $arquivotar #descompacta gz #tar -jxvf $arquivotar # descompacta bz2 # para cada pasta aberta (ou seja, para cada dia)... for ((i=0; i <= 30 ; i++)) do diretorio="$ano-"${mes[$m]}"-"${dia[$i]}"" arq="$ano-"${mes[$m]}"-"${dia[$i]}".dat" # se o diretorio existir if test -d $diretorio then # para cada arquivo de 15 min for ((h=0; h <= 95 ; h++)); do arquivo="$ano-"${mes[$m]}"-"${dia[$i]}"_"${hora[$h]}".dat" # se arquivo existir, concatenar o arquivo dentro do arquivo final test -f $diretorio/$arquivo && cat $diretorio/$arquivo >> $ndir/$arq done # apagar pasta do dia rm -rf $diretorio # compactar arquivo gzip $ndir/$arq fi done # mover a pasta para dados mv $ndir ../../dados fi done
Fontes: Viva o Linux – Brincando com vetores e Stack Overflow.
2 comments