Successfully reported this slideshow.

Curso de Shell Script 07/11

336 views

Published on

De pouco adianta ter acesso à informação se ela não puder ser apresentada de forma atraente e que facilite a compreensão. O comando tput pode ser usado por shell scripts para posicionar caracteres e criar todos os tipos de efeito com o texto mostrado na tela. Garçom, solta uma geladinha!

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Curso de Shell Script 07/11

  1. 1. Linux User Papo de botequim Papo de Botequim Curso de Shell Script Parte VII Dave Hamilton - www.sxc.hu De pouco adianta ter acesso à informação se ela não puder ser apresentada de forma atraente e que facilite a compreensão. O comando tput pode ser usado por shell scripts para posicionar caracteres e criar todos os tipos de efeito com o texto mostrado na tela. Garçom, solta uma geladinha! por Julio Cezar Neves C umequié, rapaz! Derreteu os pen- – Peraí, deixa eu ver se entendi o que você – É, tô vendo que o bichinho do shell te samentos para fazer o scriptzinho fez: você coloca na variável Dir a última pegou. Vamos ver como ler dados, mas que eu te pedi? linha do arquivo a ser restaurado, em antes vou te mostrar um comando que – É, eu realmente tive de colocar muita nosso caso /tmp/$LOGNAME/$1 (onde te dá todas as ferramentas para formatar pensação na tela preta, mas acho que $LOGNAME é o nome do usuário logado, uma tela de entrada de dados. fi nalmente consegui! Bem, pelo menos e $1 é o primeiro parâmetro que você nos testes que fi z a coisa funcionou, passou ao script), já que foi lá que arma- O comando tput mas você tem sempre que botar chifres zenamos o nome e caminho originais do O principal uso desse comando é o posi- em cabeça de cachorro! arquivo antes de movê-lo para o diretório cionamento do cursor na tela. Alguns – Não é bem assim. É que programar em (defi nido na variável Dir). O comando parâmetros podem não funcionar se o Shell Script é muito fácil, mas o que é grep -v apaga essa linha, restaurando modelo de terminal defi nido pela vari- realmente importante são as dicas e o arquivo ao estado original, e o manda ável de ambiente $TERM não suportá-los. macetes que não são triviais. As cor- de volta pra onde ele veio. A última linha A tabela 1 apresenta apenas os principais reções que faço são justamente para o apaga da “lixeira”. Sensacional! Impe- parâmetros e os efeitos resultantes, mas mostrá-los. Mas vamos pedir dois cho- cável! Nenhum erro! Viu? Você já está existem muito mais deles. Para saber tudo pes enquanto dou uma olhadela no teu pegando as manhas do shell! sobre o tput, veja a referência [1]. script lá na listagem 1. Aê Chico, traz – Então vamos lá, chega de lesco-lesco Vamos fazer um programa bem besta dois chopes! E não se esqueça que um e blá-blá-blá, sobre o quê nós vamos e fácil para ilustrar melhor o uso desse deles é sem colarinho! falar hoje? comando. É uma versão do famigerado “Alô Mundo”, só que dessa vez a frase Listagem 1 – restaura.sh será escrita no centro da tela e em vídeo reverso. Depois disso, o cursor voltará para 01 #!/bin/bash a posição original. Veja a listagem 2. 02 # Como o programa já está todo comen- 03 # Restaura arquivos deletados via erreeme tado, acho que a única linha que precisa de 04 # explicação é a 8, onde criamos a variável 05 Coluna. O estranho ali é aquele número 06 if [ $# -eq 0 ] 9, que na verdade indica o tamanho da 07 then cadeia de caracteres que vou escrever na 08 echo "Uso: $0 <Nome do arquivo a ser restaurado>" tela. Dessa forma, este programa somente 09 exit 1 conseguiria centralizar cadeias de 9 carac- 10 fi teres, mas veja isto: 11 # Pega nome do arquivo/diretório original na última linha 12 Dir=tail -1 /tmp/$LOGNAME/$1 $ var=Papo 13 # O grep -v exclui a última linha e recria o arquivo com o diretório $ echo ${#var} 14 # e nome originalmente usados 4 15 grep -v $Dir /tmp/$LOGNAME/$1 > $Dir/$1 $ var="Papo de Botequim" 16 # Remove o arquivo que já estava moribundo $ echo ${#var} 17 rm /tmp/$LOGNAME/$1 1686 abril 2005 edição 07 www.linuxmagazine.com.br
  2. 2. Linux User Papo de botequim Tabela 1: Parâmetros do tput e a linha 12 (echo $1) passaria a ser: Parâmetro Efeito echo $* cup lin col CUrsor Position – Posiciona o cursor na linha lin e coluna col. A origem (0,0) fica no canto superior esquerdo da tela. Lendo dados da tela bold Coloca a tela em modo negrito Bem, a partir de agora vamos aprender rev Coloca a tela em modo de vídeo reverso tudo sobre leitura. Só não posso ensinar a ler cartas e búzios porque se soubesse smso Idêntico ao anterior estaria rico, num pub Londrino tomando smul Sublinha os caracteres um scotch e não em um boteco tomando blink Deixa os caracteres piscando chope. Mas vamos em frente. sgr0 Restaura a tela a seu modo normal Da última vez em que nos encontramos reset Limpa o terminal e restaura suas definições de acordo com terminfo, ou seja, o ter- eu dei uma palhinha sobre o comando minal volta ao comportamento padrão definido pela variável de ambiente $TERM read. Antes de entrarmos em detalhes, veja só isso: lines Informa a quantidade de linhas que compõem a tela cols Informa a quantidade de colunas que compõem a tela $ read var1 var2 var3 el Erase Line – Apaga a linha a partir da posição do cursor Papo de Botequim ed Erase Display – Apaga a tela a partir da posição do cursor $ echo $var1 Papo il n Insert Lines – Insere n linhas a partir da posição do cursor $ echo $var2 dl n Delete Lines – Remove n linhas a partir da posição do cursor de dch n Delete CHaracters – Apaga n caracteres a partir da posição do cursor $ echo $var3 sc Save Cursor position – Salva a posição do cursor Botequim rc Restore Cursor position – Coloca o cursor na posição marcada pelo último sc $ read var1 var2 Papo de Botequim $ echo $var1 Ahhh, melhorou! Então agora sabemos essa construção devolve o número de Papo que a construção ${#variavel} devolve caracteres do primeiro parâmetro pas- $ echo $var2 a quantidade de caracteres da variável. sado para o programa. Se o parâmetro de Botequim Assim sendo, vamos otimizar o nosso tivesse espaços em branco, seria preciso programa para que ele escreva em vídeo colocá-lo entre aspas, senão o $1 leva- Como você viu, o read recebe uma reverso, no centro da tela (e indepen- ria em conta somente o pedaço antes lista de parâmetros separada por espa- dente do número de caracteres) a cadeia do primeiro espaço. Para evitar este ços em branco e coloca cada item dessa de caracteres passada como parâmetro e aborrecimento, é só substituir o $1 por lista em uma variável. Se a quantidade depois retorne o cursor à posição em que $*, que como sabemos é o conjunto de de variáveis for menor que a quantidade estava antes da execução do script. Veja todos os parâmetros. Então a linha 8 de itens, a última variável recebe o res- o resultado na listagem 3. ficaria assim: tante deles. Eu disse lista separada por Este script é igual ao anterior, só que espaços em branco, mas agora que você trocamos o valor fixo na variável Coluna # Centralizando a mensagem na tela já conhece tudo sobre o $IFS (Inter Field (9) por ${#1}, onde esse 1 é $1, ou seja, Coluna=`$(((Colunas - ${#*}) / 2))` Separator – Separador entre campos), que Listagem 2: alo.sh Listagem 3: alo.sh melhorado 01 #!/bin/bash 01 #!/bin/bash 02 # Script bobo para testar 02 # Script bobo para testar 03 # o comando tput (versao 1) 03 # o comando tput (versão 2.0) 04 04 05 Colunas=`tput cols` # Salva a quantidade de colunas na tela 05 Colunas=`tput cols` # Salva a quantidade de colunas na tela 06 Linhas=`tput lines` # Salva a quantidade linhas na tela 06 Linhas=`tput lines` # Salva a quantidade de linhas na tela 07 Linha=$((Linhas / 2)) # Qual é a linha central da tela? 07 Linha=$((Linhas / 2)) # Qual é a linha central da tela? 08 Coluna=$(((Colunas - 9) / 2)) # Centraliza a mensagem na tela 08 Coluna=$(((Colunas - ${#1}) / 2)) # Centraliza a mensagem na tela 09 tput sc # Salva a posição do cursor 09 tput sc # Salva a posicao do cursor 10 tput cup $Linha $Coluna # Posiciona o cursor antes de escrever 10 tput cup $Linha $Coluna # Posiciona o cursor antes de escrever 11 tput rev # Vídeo reverso 11 tput rev # Video reverso 12 echo Alô Mundo 12 echo $1 13 tput sgr0 # Restaura o vídeo ao normal 13 tput sgr0 # Restaura o vídeo ao normal 14 tput rc # Restaura o cursor à posição original 14 tput rc # Devolve o cursor à posição original88 abril 2005 edição 07 www.linuxmagazine.com.br
  3. 3. Papo de botequim Linux Usereu te apresentei quando falávamos do para que o n fosse entendido como $ read -t2 -p "Digite seu nome completo: Ucomando for, será que ainda acredita uma quebra de linha (new line) e não " Nom || echo Eita moleza!nisso? Vamos testar: como um literal. Sob o Bash exis- Digite seu nome completo: Eita moleza! tem diversas opções do read que ser- $ echo $Nom$ oIFS="$IFS" vem para facilitar a sua vida. Veja$ IFS=: a tabela 2. O exemplo acima foi uma brincadeira,$ read var1 var2 var3 E agora direto aos exemplos curtos pois eu só tinha 2 segundos para digitar oPapo de Botequim para demonstrar estas opções. Para ler meu nome completo e mal tive tempo de$ echo $var1 um campo “Matrícula”: teclar um J (aquele colado no Eita), masPapo de Botequim ele serviu para mostrar duas coisas:$ echo $var2 # -n não salta linha P 1) O comando após o par de barras verti-$ echo $var3 $ echo -n "Matricula: "; read Mat cais (o ou – or – lógico, lembra-se?) será$ read var1 var2 var3 Matricula: 12345 executado caso a digitação não tenhaPapo:de:Botequim $ echo $Mat sido concluída no tempo estipulado;$ echo $var1 12345 P 2) A variável Nom permaneceu vazia. ElaPapo só receberá um valor quando o ENTER$ echo $var2 Podemos simplificar as coisas usando for teclado.de a opção -p:$ echo $var3 $ read -sp “Senha: “Botequim $ read -p "Matricula: " Mat Senha: $ echo $REPLY$ IFS="$oIFS" Matricula: 12345 segredo :) $ echo $Mat Viu? eu estava furado! O read lê uma 12345 Aproveitei um erro no exemplo ante-lista, assim como o for, separada pelos rior para mostrar um macete. Quandocaracteres da variável $IFS. Veja como E podemos ler apenas uma quantidade escrevi a primeira linha, esqueci de colo-isso pode facilitar a sua vida: pré-determinada de caracteres: car o nome da variável que iria receber a senha e só notei isso quando ia escrevê-$ grep julio /etc/passwd $ read -n5 -p"CEP: " Num ; read -n3 U la. Felizmente a variável $REPLY do Bashjulio:x:500:544:Julio C. Neves - 7070:U -p- Compl contém a última seqüência de caracteres/home/julio:/bin/bash CEP: 12345-678$ digitada – e me aproveitei disso para não$ oIFS="$IFS" # Salva o IFS antigo. $ echo $Num perder a viagem. Teste você mesmo o que$ IFS=: 12345 acabei de fazer.$ grep julio /etc/passwd | read lname U $ echo $Compl O exemplo que dei, na verdade, era paralixo uid gid coment home shell 678 mostrar que a opção -s impede que o que$ echo -e "$lnamen$uidn$gidn$comentU está sendo digitado seja mostrado na tela.n$homen$shell" No exemplo acima executamos duas Como no exemplo anterior, a falta do newjulio vezes o comando read: um para a pri- line fez com que o prompt de comando500 meira parte do CEP e outra para o seu ($) permanecesse na mesma linha.544 complemento, deste modo formatando Agora que sabemos ler da tela, vejamosJulio C. Neves - 7070 a entrada de dados. O cifrão ($) logo como se lêem os dados dos arquivos./home/julio após o último algarismo digitado é/bin/bash necessário porque o read não inclui Lendo arquivos$ IFS="$oIFS" # Restaura o IFS por padrão um caractere new line Como eu já havia lhe dito, e você deve se implícito, como o echo. lembrar, o while testa um comando e exe- Como você viu, a saída do grep foi Para ler só durante um determinado cuta um bloco de instruções enquanto esseredirecionada para o comando read, limite de tempo (também conhecido comando for bem sucedido. Ora, quandoque leu todos os campos de uma só como time out): você está lendo um arquivo para o qualtacada. A opção -e do echo foi usada você tem permissão de leitura, o read só será mal sucedido quando alcançar o EOF Tabela 2: Opções do read (End Of File – Fim do Arquivo). Portanto, podemos ler um arquivo de duas maneiras. Opção Ação A primeira é redirecionando a entrada do-p prompt Escreve “prompt” na tela antes de fazer a leitura arquivo para o bloco while, assim:-n num Lê até num caracteres while read Linha-t seg Espera seg segundos para que a leitura seja concluída do-s Não exibe na tela os caracteres digitados. echo $Linha done < arquivo abril 2005 edição 07 89 www.linuxmagazine.com.br
  4. 4. Linux User Papo de botequim A segunda é redirecionando a saída Como você viu, o script lista suas pró- que vou mostrar com um exemplo prático. de um cat para o while, da seguinte prias linhas com um sinal de menos (-) Suponha que você queira listar um arquivo maneira: antes e outro depois de cada uma e, no e quer que a cada dez registros essa listagem final, exibe o conteúdo da variável $Ultimo. pare para que o operador possa ler o con- cat arquivo | Repare, no entanto, que o conteúdo dessa teúdo da tela, e que ela só continue depois while read Linha variável permanece vazio. Ué, será que de o operador pressionar qualquer tecla. do a variável não foi atualizada? Foi, e isso Para não gastar papel (da Linux Magazine), echo $Linha pode ser comprovado porque a linha echo vou fazer essa listagem na horizontal. Meu done "-$Ultimo-" lista corretamente as linhas. arquivo (numeros) tem 30 registros com Então por que isso aconteceu? números seqüenciais. Veja: Cada um dos processos tem suas van- Como eu disse, o bloco de instruções tagens e desvantagens. O primeiro é mais redirecionado pelo pipe (|) é executado $ seq 30 > numeros rápido e não necessita de um subshell em um subshell e, lá, as variáveis são $ cat 10porpag.sh para assisti-lo mas, em contrapartida, o atualizadas. Quando esse subshell ter- #!/bin/bash redirecionamento fica pouco visível em mina, as atualizações das variáveis vão # Programa de teste para escrever um bloco de instruções grande, o que para as profundezas do inferno junto com # 10 linhas e parar para ler por vezes prejudica a visualização do ele. Repare que vou fazer uma pequena # Versão 1 código. O segundo processo traz a van- mudança no script, passando o arquivo while read Num tagem de que, como o nome do arquivo por redirecionamento de entrada (<), e do está antes do while, a visualização do as coisas passarão a funcionar na mais let ContLin++ # Contando... código é mais fácil. Entretanto, o Pipe perfeita ordem: # -n para não saltar linha (|) chama um subshell para interpretá-lo, echo -n "$Num " tornando o processo mais lento e pesado. $ cat redirread.sh ((ContLin % 10)) > /dev/null || read Para ilustrar o que foi dito, veja os exem- #!/bin/bash done < numeros plos a seguir: # redirread.sh # Exemplo de read passando o arquivo Na tentativa de fazer um programa $ cat readpipe.sh # por um pipe. genérico criamos a variável $ContLin (na #!/bin/bash Ultimo="(vazio)" vida real, os registros não são somente # readpipe.sh # Passa o script ($0) para o while números seqüenciais) e, quando testamos # Exemplo de read passando um arquivo while read Linha se o resto da divisão era zero, mandamos # por um pipe. do a saída para /dev/null, pra que ela não Ultimo="(vazio)" Ultimo="$Linha" apareça na tela. Mas quando fui executar # Passa o script ($0) para o while echo "-$Ultimo-" o programa descobri a seguinte zebra: cat $0 | while read Linha done < $0 do echo "Acabou, Último=:$Ultimo:" $ 10porpag.sh Ultimo="$Linha" 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 U echo "-$Ultimo-" Veja como ele roda perfeitamente: 18 19 20 21 23 24 25 26 27 28 29 30 done echo "Acabou, Último=:$Ultimo:" $ redirread.sh Repare que faltou o número 11 e a lista- -#!/bin/bash- gem não parou no read. Toda a entrada do Vamos ver o resultado de sua execução: -# redirread.sh- loop estava redirecionada para o arquivo -# Exemplo de read passando o arquivo numeros e a leitura foi feita em cima desse $ readpipe.sh -# por um pipe.- arquivo, perdendo o número 11. Vamos -#!/bin/bash- -- mostrar como deveria ficar o código para -# readpipe.sh- -Ultimo="(vazio)"- que ele passe a funcionar a contento: -# Exemplo de read passando um arquivo -while read Linha- -# por um pipe.- -do- $ cat 10porpag.sh -- -Ultimo="$Linha"- #!/bin/bash -Ultimo="(vazio)"- -echo "-$Ultimo-"- # Programa de teste para escrever -# Passa o script ($0) para o while- -# Passa o script ($0) para o while- # 10 linhas e parar para ler - Versão 2 -cat $0 | - -done < $0- while read Num -while read Linha- -echo "Acabou, Último=:$Ultimo:"- do -do- Acabou, Último=:echo "Acabou,U let ContLin++ # Contando... -Ultimo="$Linha"- Último=:$Ultimo:": # -n para não saltar linha -echo "-$Ultimo-"- echo -n "$Num " -done- Bem, amigos da Rede Shell, para finali- ((ContLin % 10)) > /dev/null || read U -echo "Acabou, Último=:$Ultimo:"- zar a aula sobre o comando read só falta < /dev/tty Acabou, Último=:(vazio): mais um pequeno e importante macete done < numeros90 abril 2005 edição 07 www.linuxmagazine.com.br
  5. 5. Papo de botequim Linux User Repare que agora a entrada do read foi # 10 linhas e parar para ler – Bem meu amigo, por hoje é só porqueredirecionada para /dev/tty, que nada # Versão 3 acho que você já está de saco cheio…mais é senão o terminal corrente, expli- clear – Num tô não, pode continuar…citando desta forma que aquela leitura while read Num – Se você não estiver eu estou… Mas jáseria feita do teclado e não do arquivo do que você está tão empolgado com o shell,numeros. É bom realçar que isso não # Contando... vou te deixar um serviço bastante sim-acontece somente quando usamos o redi- ((ContLin++)) ples para você melhorar a sua cdteca:recionamento de entrada; se tivéssemos echo "$Num" Monte toda a tela com um único echousado o redirecionamento via pipe (|), o ((ContLin % (`tput lines` - 3))) || e depois posicione o cursor à frente demesmo teria ocorrido. Veja agora a exe- { cada campo para receber o valor quecução do script: # para ler qualquer caractere será digitado pelo operador. read -n1 -p"Tecle Algo " < /dev/tty Não se esqueçam que, em caso de$ 10porpag.sh # limpa a tela após a leitura qualquer dúvida ou falta de companhia1 2 3 4 5 6 7 8 9 10 clear para um chope é só mandar um e-mail11 12 13 14 15 16 17 18 19 20 } para julio.neves@gmail.com. Vou aproveitar21 22 23 24 25 26 27 28 29 30 done < numeros também para fazer uma propaganda: digam aos amigos que quem estiver a Isso está quase bom, mas ainda falta A mudança substancial feita neste exem- fim de fazer um curso “porreta” de pro-um pouco para ficar excelente. Vamos plo é com relação à quebra de página, já gramação em shell deve mandar um e-melhorar o exemplo para que você o que ela é feita a cada quantidade-de-linhas- mail para julio.neves@tecnohall.com.br parareproduza e teste (mas, antes de testar, da-tela (tput lines) menos (-) três, isto informar-se. Até mais!aumente o número de registros em nume- é, se a tela tem 25 linhas, o programaros ou reduza o tamanho da tela, para listará 22 registros e parará para leitura. Informaçõesque haja quebra de linha). No comando read também foi feita uma [1] Página oficial do Tput: http://www.cs.utah.edu/ alteração, inserido o parâmetro -n1 para dept/old/texinfo/tput/tput.html#SEC4$ cat 10porpag.sh ler somente um caractere qualquer, não [2] Página oficial do Bash: http://www.gnu.org/#!/bin/bash necessariamente um ENTER, e a opção software/bash/bash.html# Programa de teste para escrever -p para exibir uma mensagem. abril 2005 edição 07 91 www.linuxmagazine.com.br

×