Curso de Shell Script 06/11

196 views

Published on

Blocos de código e laços (ou loops, como preferem alguns) são o tema do mês em mais uma lição de nosso curso de Shell Script. Garçom, salta uma boa redondinha, que tô a fim de refrescar o pensamento!

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
196
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Curso de Shell Script 06/11

  1. 1. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim Curso de Shell Script Papo de Botequim VI Blocos de código e laços (ou loops, como preferem alguns) Dave Hamilton - www.sxc.hu são o tema do mês em mais uma lição de nosso curso de Shell Script. Garçom, salta uma boa redondinha, que tô a fim de refrescar o pensamento! POR JULIO CEZAR NEVES F ala, cara! E aí, já tá sabendo tudo do comando for? Eu te deixei um exercício para treinar, se não me engano era para contar a quantidade de palavras de um arquivo... Você fez? Ou seja, o programa começa, como sempre, verificando se a passagem de parâmetros foi correta; em seguida o comando for se incumbe de pegar cada uma das palavras (lembre-se que o $IFS Uma vez que chegamos neste ponto, creio ser interessante citar que o Shell trabalha com o conceito de “Expansão Aritmética” (Arithmetic Expansion), que é acionada por uma construção da – Claro! Tô empolgadão com essa lin- padrão é branco, TAB e ENTER, que é forma $((expressão)) ou let expressão. guagem! Eu fi z da forma que você exatamente o que desejamos para sepa- No último loop for usei a expansão pediu, olha só... rar as palavras), incrementando a vari- aritmética das duas formas, mas não – Êpa! Peraí que eu tô sequinho pra ável $Cont. Vamos relembrar como é o podemos seguir adiante sem saber que tomar um chope. Aê Chico, traz dois arquivo ArqDoDOS.txt. a expressão pode ser uma das listadas por favor. Um sem colarinho! na tabela 1. – Como eu ia dizendo, olha como eu fi z. $ cat ArqDoDOS.txt Mas você pensa que o papo de loop É muito fácil... Este arquivo (ou laço) se encerra no comando for? foi gerado pelo Ledo engano, amigo, vamos a partir de $ cat contpal.sh DOS/Rwin e foi agora ver mais dois comandos. #!/bin/bash baixado por um # Script meramente pedagógico ftp mal feito. O comando while # cuja função é contar a Todos os programadores conhecem este # quantidade de palavras de Agora vamos testar o programa pas- comando, porque é comum a todas as # um arquivo. Supõe-se que as sando esse arquivo como parâmetro: linguagens. Nelas, o que normalmente # palavras estão separadas ocorre é que um bloco de comandos é # entre si por espaços, <TAB> $ contpal.sh ArqDoDOS.txt executado, enquanto (enquanto, em # ou <ENTER>. O arquivo ArqDoDOS.txt tem 14 inglês, é “while”) uma determinada if [ $# -ne 1 ] palavras. condição for verdadeira. then echo uso: $0 /caminho/do/ U Funcionou legal! Tabela 1: Expressões no Shell arquivo Se você se lembra, Expressão Resultado exit 2 em nossa última id++ id-- pós-incremento e pós-decremento de variáveis fi aula mostramos o ++id --id pré-incremento e pré-decremento de variáveis Cont=0 loop for a seguir: ** exponenciação for Palavra in $(cat $1) */% multiplicação, divisão, resto da divisão (módulo) do for ((; i<=9;)) +- adição, subtração Cont=$((Cont+1)) do <= >= < > comparação == != igualdade, desigualdade done let i++ && E lógico echo O arquivo $1 tem $Cont U echo -n "$i " || OU lógico palavras. done����������������������������� 86 edição 06 www.linuxmagazine.com.br��������������������������������������������������������������������������������
  2. 2. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER Pois bem, isso é o que acontece nas $ logaute.sh $cat monbg.sh linguagens caretas! Em programação xefe pts/0 Jan 4 08:46 U #!/bin/bash Shell, o bloco de comandos é executado (10.2.4.144) # Executa e monitora um enquanto um comando for verdadeiro. xefe pts/0 Jan 4 08:46 U # processo em background E é claro, se quiser testar uma condi- (10.2.4.144) $1 & # Coloca em backgroud ção, use o comando while junto com o ... while ps | grep -q $! comando test, exatamente como você xefe pts/0 Jan 4 08:46 U do aprendeu a fazer no if, lembra? Então a (10.2.4.144) sleep 5 sintaxe do comando fica assim: done Isto é, a cada 30 segundos a saída do echo Fim do Processo $1 while comando comando grep seria enviada para a tela, do o que não é legal, já que poluiria a tela Esse script é bastante similar ao ante- cmd1 do meu micro e a mensagem tão espe- rior, mas tem uns macetes a mais, veja cmd2 rada poderia passar despercebida. Para só: ele tem que ser executado em back- ... evitar isso, já sabemos que a saída do ground para não prender o prompt mas cmdn pipeline tem que ser redirecionada para o $! será o do programa passado como done o dispositivo /dev/null. parâmetro, já que ele foi colocado em background após o monbg.sh propria- e dessa forma, o bloco formado pelas $ cat logaute.sh mente dito. Repare também na opção -q instruções cmd1, cmd2,... e cmdn é exe- #!/bin/bash (quiet) do grep, que serve para fazê-lo cutado enquanto a execução da instru- # Espero que a Xuxa não tenha “trabalhar em silêncio”. O mesmo resul- ção comando for bem sucedida. # copyright de xefe e xato :) tado poderia ser obtido com a linha: Suponha a seguinte cena: tinha while who | grep xefe > /dev/null while ps | grep $! > /dev/null, como nos uma tremenda gata me esperando e do exemplos que vimos até agora. eu estava preso no trabalho sem poder sleep 30 Vamos melhorar o nosso velho sair porque o meu chefe, que é um pé done musinc, nosso programa para incluir no saco (aliás chefe-chato é uma redun- echo O xato se mandou, não U registros no arquivo musicas, mas dância, né?), ainda estava na sala dele, hesite, dê exit e vá a luta antes preciso te ensinar a pegar que fica bem na minha passagem para a um dado da tela, e já vou avisando: rua. Ele começou a ficar cabreiro depois Agora quero montar um script que só vou dar uma pequena dica do da quinta vez que passei pela sua porta receba o nome (e eventuais parâme- comando read (que é quem pega o e olhei para ver se já havia ido embora. tros) de um programa que será execu- dado da tela), que seja o suficiente Então voltei para a minha mesa e fi z, no tado em background e que me informe para resolver este nosso problema. servidor, um script assim: do seu término. Mas, para você enten- Em uma outra rodada de chope vou der este exemplo, primeiro tenho de te ensinar tudo sobre o assunto, $ cat logaute.sh mostrar uma nova variável do sistema. inclusive como formatar tela, mas #!/bin/bash Veja estes comandos executados direta- hoje estamos falando sobre loops. A # Espero que a Xuxa não tenha mente no prompt: sintaxe do comando read que nos # copyright de xefe e xato :) interessa por hoje é a seguinte: while who | grep xefe $ sleep 10& do [1] 16317 $ read -p "prompt de leitura" var sleep 30 $ echo $! done 16317 Onde “prompt de leitura” é o texto echo O xato se mandou, não U [1]+ Done sleep 10 que você quer que apareça escrito na hesite, dê exit e vá à luta $ echo $! tela. Quando o operador teclar tal dado, 16317 ele será armazenado na variável var. Neste scriptzinho, o comando while Por exemplo: testa o pipeline composto pelos coman- Isto é, criei um processo em back- dos who e grep, que será verdadeiro ground que dorme por 10 segundos, $ read -p "Título do Álbum: " Tit enquanto o grep localizar a palavra somente para mostrar que a variável $! xefe na saída do comando who. Desta guarda o PID (Process ID) do último pro- Bem, uma vez entendido isso, vamos forma, o script dormirá por 30 segundos cesso em background. Mas observe a à especificação do nosso problema: enquanto o chefe estiver logado (Argh!). listagem e repare, após a linha do Done, faremos um programa que inicialmente Assim que ele se desconectar do servi- que a variável reteve o valor mesmo lerá o nome do álbum e em seguida fará dor, o fluxo do script sairá do loop e te após o término desse processo. um loop de leitura, pegando o nome da mostrará a tão ansiada mensagem de Bem, sabendo isso, já fica mais fácil música e o artista. Esse loop termina liberdade. Mas quando executei o script, monitorar qualquer processo em back- quando for informada uma música com adivinha o que aconteceu? ground. Veja só como: nome vazio, isto é, quando o operador ����������������������������� www.linuxmagazine.com.br edição 06 87 ��������������������������������������������������������������������������������
  3. 3. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim Dica until comando $cat chegada.sh Leitura de arquivo significa ler um a um do #!/bin/bash todos os registros, o que é sempre uma cmd1 until who | grep julio operação lenta. Fique atento para não usar cmd2 do o while quando for desnecessário. O Shell ... sleep 30 tem ferramentas como o sed e a família cmdn done grep, que vasculham arquivos de forma done echo $(date "+ Em %d/%m às U otimizada sem que seja necessário o uso do %H:%Mh") > relapso.log while para fazê-lo registro a registro. e dessa forma o bloco de comandos for- mado pelas instruções cmd1, cmd2,... e Olha que safado! O cara estava mon- der um simples <ENTER>. Para facili- cmdn é executado até que a execução da tando um log com os meus horários de tar a vida do operador, vamos oferecer instrução comando seja bem sucedida. chegada, e ainda por cima chamou o como default o mesmo nome do artista Como eu te disse, while e until funcio- arquivo de relapso.log! O que será que da música anterior (já que é normal que nam de forma antagônica, e isso é muito ele quis dizer com isso? o álbum seja todo do mesmo artista) até fácil de demonstrar: em uma guerra, Nesse script, o pipeline who | grep que ele deseje alterá-lo. Veja na listagem sempre que se inventa uma arma, o julio, será bem sucedido somente 1 como ficou o programa. inimigo busca uma solução para neu- quando julio for encontrado na saída Nosso exemplo começa com a lei- tralizá-la. Foi baseado nesse principio do comando who, isto é, quando eu tura do título do álbum. Caso ele não belicoso que meu chefe desenvolveu, no me “logar” no servidor. Até que isso seja informado, terminamos a execu- mesmo servidor em que eu executava o aconteça, o comando sleep, que forma ção do programa. Em seguida um grep logaute.sh, um script para controlar o o bloco de instruções do until, colocará procura, no início (^) de cada registro meu horário de chegada. o programa em espera por 30 segun- de músicas, o título informado seguido Um dia tivemos um problema na rede. dos. Quando esse loop encerrar-se, será do separador (^) (que está precedido de Ele me pediu para dar uma olhada no enviada uma mensagem para o arquivo uma contrabarra [] para protegê-lo da micro dele e me deixou sozinho na sala. relapso.log. Supondo que no dia 20/01 interpretação do Shell). Resolvi bisbilhotar os arquivos – guerra eu me “loguei” às 11:23 horas, a mensa- Para ler os nomes dos artistas e as é guerra – e veja só o que descobri: gem seria a seguinte: músicas do álbum, foi montado um loop while simples, cujo único destaque é o Listagem 1 fato de ele armazenar o nome do intér- $ cat musinc.sh prete da música anterior na variável #!/bin/bash $oArt, que só terá o seu conteúdo alte- # Cadastra CDs (versao 4) rado quando algum dado for informado # para a variável $Art, isto é, quando não clear for teclado um simples ENTER para read -p "Título do Álbum: " Tit manter o artista anterior. [ "$Tit" ] || exit 1 # Fim da execução se título vazio O que foi visto até agora sobre o while if grep "^$Tit^" musicas > /dev/null foi muito pouco. Esse comando é muito then utilizado, principalmente para leitura echo "Este álbum já está cadastrado" de arquivos, porém ainda nos falta exit 1 bagagem para prosseguir. Depois que fi aprendermos mais sobre isso, veremos Reg="$Tit^" essa instrução mais a fundo. Cont=1 O comando until oArt= while true Este comando funciona de forma do idêntica ao while, porém ao contrário. echo "Dados da trilha $Cont:" Disse tudo mas não disse nada, né? É read -p "Música: " Mus o seguinte: ambos testam comandos; [ "$Mus" ] || break # Sai se vazio ambos possuem a mesma sintaxe e read -p "Artista: $oArt // " Art ambos atuam em loop; porém, o while [ "$Art" ] && oArt="$Art" # Se vazio Art anterior executa o bloco de instruções do loop Reg="$Reg$oArt~$Mus:" # Montando registro enquanto um comando for bem suce- Cont=$((Cont + 1)) dido; já o until executa o bloco do loop # A linha anterior tb poderia ser ((Cont++)) até que o comando seja bem sucedido. done Parece pouca coisa, mas a diferença é echo "$Reg" >> musicas fundamental. A sintaxe do comando é sort musicas -o musicas praticamente a mesma do while. Veja:����������������������������� 88 edição 06 www.linuxmagazine.com.br��������������������������������������������������������������������������������
  4. 4. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER Em 20/01 às 11:23h Atalhos no loop �� �� Voltando à nossa CDteca, quando Nem sempre um �������� �������� vamos cadastrar músicas seria ideal ciclo de programa, que pudéssemos cadastrar diversos compreendido CDs de uma vez só. Na última versão entre um do e um ����� ����� ����� �������� do programa isso não ocorre: a cada CD done, sai pela porta cadastrado o programa termina. Veja na da frente. Em algu- �������� �������� listagem 2 como melhorá-lo. mas oportunidades, Nesta versão, um loop maior foi adi- temos que colocar ���� ���� cionado antes da leitura do título, que um comando que só terminará quando a variável $Para aborte de forma deixar de ser vazia. Caso o título do c ont rolada esse �������������������� ����������������������� álbum não seja informado, a variá- loop. De maneira Figura 1: A estrutura dos comandos break e continue, usados para contro- vel $Para receberá um valor (coloquei inversa, algumas lar o fluxo de execução em loops. 1, mas poderia ter colocado qualquer vezes desejamos coisa) para sair desse loop, terminando que o f lu xo de pectivamente os comandos break (que o programa. No resto, o script é idênticoexecução do programa volte antes de já vimos rapidamente nos exemplos do à versão anterior. chegar ao done. Para isso, temos res- comando while) e continue, que funcio- nam da forma mostrada na figura 1. Listagem 2 O que eu não havia dito anterior- mente é que nas suas sintaxes genéricas $ cat musinc.sh eles aparecem da seguinte forma: #!/bin/bash # Cadastra CDs (versao 5) break [qtd loop] # Para= e também: until [ "$Para" ] do continue [qtd loop] clear read -p "Título do Álbum: " Tit Onde qtd loop representa a quanti- if [ ! "$Tit" ] # Se titulo vazio... dade dos loops mais internos sobre os then quais os comandos irão atuar. Seu valor Para=1 # Liguei flag de saída por default é 1. else Duvido que você nunca tenha apa- if grep "^$Tit^" musicas > /dev/null gado um arquivo e logo após deu um then tabefe na testa se xingando porque echo "Este álbum já está cadastrado" não devia tê-lo removido. Pois é, na exit 1 décima vez que fi z esta besteira, criei fi um script para simular uma lixeira, Reg="$Tit^" isto é, quando mando remover um (ou Cont=1 vários) arquivo(s), o programa “fi nge” oArt= que deletou, mas no duro o que ele fez while [ "$Tit" ] foi mandá-lo(s) para o diretório /tmp/ do LoginName_do_usuario. Chamei esse echo Dados da trilha $Cont: programa de erreeme e no arquivo /etc/ read -p "Música: " Mus profile coloquei a seguinte linha, que [ "$Mus" ] || break # Sai se vazio cria um “apelido” para ele: read -p "Artista: $oArt // " Art [ "$Art" ] && oArt="$Art" # Se vazio Art anterior alias rm=erreeme Reg="$Reg$oArt~$Mus:" # Montando registro Cont=$((Cont + 1)) Veja o programa na listagem 3. Como # A linha anterior tb poderia ser ((Cont++)) você pode ver, a maior parte do script done é formada por pequenas críticas aos echo "$Reg" >> musicas parâmetros informados, mas como o sort musicas -o musicas script pode ter recebido diversos arqui- fi vos a remover, a cada arquivo que não done se encaixa dentro do especificado há ����������������������������� www.linuxmagazine.com.br edição 06 89 ��������������������������������������������������������������������������������
  5. 5. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim Listagem 3: erreeme.sh $ cat erreeme.sh then #!/bin/bash echo "$Arq nao existe." # Erro=3 # Salvando cópia de um arquivo antes de removê-lo continue # Volta para o comando for fi # Tem de ter um ou mais arquivos a remover if [ $# -eq 0 ] # Cmd. dirname informa nome do dir de $Arq then DirOrig=`dirname $Arq` echo "Erro -> Uso: erreeme arq [arq] ... [arq]" # Verifica permissão de gravacao no diretório echo "O uso de metacaracteres e’ permitido. Ex.U if [ ! -w $DirOrig ] erreeme arq*" then exit 1 echo "Sem permissão no diretorio de $Arq" fi Erro=4 continue # Volta para o comando for # Variável do sistema que contém o nome do usuário. fi MeuDir="/tmp/$LOGNAME" # Se não existir o meu diretório sob o /tmp... # Se estou "esvaziando a lixeira"... if [ ! -d $MeuDir ] if [ "$DirOrig" = "$MeuDir" ] then then mkdir $MeuDir # Vou criá-lo echo "$Arq ficara sem copia de seguranca" fi rm -i $Arq # Pergunta antes de remover # Será que o usuário removeu? # Se não posso gravar no diretório... [ -f $Arq ] || echo "$Arquivo removido" if [ ! -w $MeuDir ] continue then fi echo "Impossivel salvar arquivos em $MeuDir. U Mude as permissões..." # Guardo no fim do arquivo o seu diretório originalU exit 2 para usá-lo em um script de undelete fi cd $DirOrig pwd >> $Arq # Variável que indica o cod. de retorno do programa mv $Arq $MeuDir # Salvo e removo Erro=0 echo "$Arq removido" # Um for sem o in recebe os parametros passados done for Arq do # Passo eventual número do erro para o código # Se este arquivo não existir... # de retorno if [ ! -f $Arq ] exit $Erro um continue, para que a seqüência volte faça-o em casa e me traga para dis- um email para julio.neves@gmail. para o loop do for de forma a receber cutirmos no nosso próximo encontro com. Agora chega de papo que eu já outros arquivos. aqui no boteco. estou de goela seca de tanto falar. Me Quando você está no Windows (com – Poxa, mas nesse eu acho que vou dan- acompanha no próximo chope ou já perdão da má palavra) e tenta remover çar, pois não sei nem como começar... vai sair correndo para fazer o script aquele monte de lixo com nomes esqui- – Cara, este programa é como tudo que passei? sitos como HD04TG.TMP, se der erro o que se faz em Shell: extrema- – Deixa eu pensar um pouco... em um dos arquivos os outros não são mente fácil. É para ser feito em, no – Chico, traz mais um chope enquanto removidos, não é? Então, o continue foi máximo, 10 linhas. Não se esqueça ele pensa! usado para evitar que uma improprie- de que o arquivo está salvo em /tmp/ dade dessas ocorra, isto é, mesmo que $LOGNAME e que sua última linha é Julio Cezar Neves é Analista de SOBRE O AUTOR dê erro na remoção de um arquivo, o o diretório em que ele residia antes Suporte de Sistemas desde 1969 e tra- programa continuará removendo os de ser “removido”. Também não se balha com Unix desde 1980, quando outros que foram passados. esqueça de criticar se foi passado o participou do desenvolvimento do – Eu acho que a esta altura você deve nome do arquivo a ser removido. SOX, um sistema operacional similar estar curioso para ver o programa – É eu vou tentar, mas sei não... ao Unix produzido pela Cobra Com- putadores. Pode ser contatado no que restaura o arquivo removido, não – Tenha fé, irmão, eu tô te falando que e-mail julio.neves@gmail.com é? Pois então aí vai vai um desafio: é mole! Qualquer dúvida é só passar����������������������������� 90 edição 06 www.linuxmagazine.com.br��������������������������������������������������������������������������������

×