SlideShare a Scribd company logo
1 of 5
Download to read offline
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
                                                                                                                         16



86   abril 2005                       edição 07
                                                                         www.linuxmagazine.com.br
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 original



88    abril 2005                              edição 07
                                                             www.linuxmagazine.com.br
Papo de botequim             Linux User



eu te apresentei quando falávamos do                para que o n fosse entendido como                  $ read -t2 -p "Digite seu nome completo: U
comando 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 o
Papo 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), mas
Papo 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 tenha
Papo:de:Botequim                                     $ echo $Mat                                          sido concluída no tempo estipulado;
$ echo $var1                                         12345                                              P 2) A variável Nom permaneceu vazia. Ela
Papo                                                                                                      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. Quando
caracteres 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 Bash
julio: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 para
lixo 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 new
julio                                               vezes o comando read: um para a pri-                line fez com que o prompt de comando
500                                                 meira parte do CEP e outra para o seu               ($) permanecesse na mesma linha.
544                                                 complemento, deste modo formatando                    Agora que sabemos ler da tela, vejamos
Julio 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 esse
redirecionada para o comando read,                  limite de tempo (também conhecido                   comando for bem sucedido. Ora, quando
que leu todos os campos de uma só                   como time out):                                     você está lendo um arquivo para o qual
tacada. 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
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 < numeros



90    abril 2005                         edição 07
                                                     www.linuxmagazine.com.br
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ó porque
redirecionada 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 echo
usado o redirecionamento via pipe (|), o          ((ContLin % (`tput lines` - 3))) ||          e depois posicione o cursor à frente de
mesmo teria ocorrido. Veja agora a exe-               {                                        cada campo para receber o valor que
cuçã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 companhia
1 2 3 4 5 6 7 8 9 10                                  clear                                   para um chope é só mandar um e-mail
11 12 13 14 15 16 17 18 19 20                         }                                       para julio.neves@gmail.com. Vou aproveitar
21 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 para
reproduza 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 programa
ros ou reduza o tamanho da tela, para        listará 22 registros e parará para leitura.                  Informações
que 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

More Related Content

Viewers also liked

Viewers also liked (8)

Linkedinppt
Linkedinppt Linkedinppt
Linkedinppt
 
A obrigatoriedade do ensino de música na escola e sua inse…
A obrigatoriedade do ensino de música na escola e sua inse…A obrigatoriedade do ensino de música na escola e sua inse…
A obrigatoriedade do ensino de música na escola e sua inse…
 
Updated CV
Updated CVUpdated CV
Updated CV
 
Curso de Shell Script 02/11
Curso de Shell Script 02/11Curso de Shell Script 02/11
Curso de Shell Script 02/11
 
MH_Logo
MH_LogoMH_Logo
MH_Logo
 
MBA Certificate
MBA CertificateMBA Certificate
MBA Certificate
 
Colorado Cancer Wellness Conference- final handout
Colorado Cancer Wellness Conference- final handoutColorado Cancer Wellness Conference- final handout
Colorado Cancer Wellness Conference- final handout
 
Packet Tracer
Packet TracerPacket Tracer
Packet Tracer
 

More from Rodrigo Silva

Curso de Shell Script 11/11
Curso de Shell Script 11/11Curso de Shell Script 11/11
Curso de Shell Script 11/11Rodrigo Silva
 
Curso de Shell Script 10/11
Curso de Shell Script 10/11Curso de Shell Script 10/11
Curso de Shell Script 10/11Rodrigo Silva
 
Curso de Shell Script 09/11
Curso de Shell Script 09/11Curso de Shell Script 09/11
Curso de Shell Script 09/11Rodrigo Silva
 
Curso de Shell Script 08/11
Curso de Shell Script 08/11Curso de Shell Script 08/11
Curso de Shell Script 08/11Rodrigo Silva
 
Curso de Shell Script 06/11
Curso de Shell Script 06/11Curso de Shell Script 06/11
Curso de Shell Script 06/11Rodrigo Silva
 
Curso de Shell Script 05/11
Curso de Shell Script 05/11Curso de Shell Script 05/11
Curso de Shell Script 05/11Rodrigo Silva
 
Curso de Shell Script 04/11
Curso de Shell Script 04/11Curso de Shell Script 04/11
Curso de Shell Script 04/11Rodrigo Silva
 
Curso de Shell Script 03/11
Curso de Shell Script 03/11Curso de Shell Script 03/11
Curso de Shell Script 03/11Rodrigo Silva
 
Curso de Shell Script 01/11
Curso de Shell Script 01/11Curso de Shell Script 01/11
Curso de Shell Script 01/11Rodrigo Silva
 

More from Rodrigo Silva (9)

Curso de Shell Script 11/11
Curso de Shell Script 11/11Curso de Shell Script 11/11
Curso de Shell Script 11/11
 
Curso de Shell Script 10/11
Curso de Shell Script 10/11Curso de Shell Script 10/11
Curso de Shell Script 10/11
 
Curso de Shell Script 09/11
Curso de Shell Script 09/11Curso de Shell Script 09/11
Curso de Shell Script 09/11
 
Curso de Shell Script 08/11
Curso de Shell Script 08/11Curso de Shell Script 08/11
Curso de Shell Script 08/11
 
Curso de Shell Script 06/11
Curso de Shell Script 06/11Curso de Shell Script 06/11
Curso de Shell Script 06/11
 
Curso de Shell Script 05/11
Curso de Shell Script 05/11Curso de Shell Script 05/11
Curso de Shell Script 05/11
 
Curso de Shell Script 04/11
Curso de Shell Script 04/11Curso de Shell Script 04/11
Curso de Shell Script 04/11
 
Curso de Shell Script 03/11
Curso de Shell Script 03/11Curso de Shell Script 03/11
Curso de Shell Script 03/11
 
Curso de Shell Script 01/11
Curso de Shell Script 01/11Curso de Shell Script 01/11
Curso de Shell Script 01/11
 

Curso de Shell Script 07/11

  • 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 16 86 abril 2005 edição 07 www.linuxmagazine.com.br
  • 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 original 88 abril 2005 edição 07 www.linuxmagazine.com.br
  • 3. Papo de botequim Linux User eu te apresentei quando falávamos do para que o n fosse entendido como $ read -t2 -p "Digite seu nome completo: U comando 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 o Papo 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), mas Papo 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 tenha Papo:de:Botequim $ echo $Mat sido concluída no tempo estipulado; $ echo $var1 12345 P 2) A variável Nom permaneceu vazia. Ela Papo 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. Quando caracteres 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 Bash julio: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 para lixo 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 new julio vezes o comando read: um para a pri- line fez com que o prompt de comando 500 meira parte do CEP e outra para o seu ($) permanecesse na mesma linha. 544 complemento, deste modo formatando Agora que sabemos ler da tela, vejamos Julio 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 esse redirecionada para o comando read, limite de tempo (também conhecido comando for bem sucedido. Ora, quando que leu todos os campos de uma só como time out): você está lendo um arquivo para o qual tacada. 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. 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 < numeros 90 abril 2005 edição 07 www.linuxmagazine.com.br
  • 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ó porque redirecionada 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 echo usado o redirecionamento via pipe (|), o ((ContLin % (`tput lines` - 3))) || e depois posicione o cursor à frente de mesmo teria ocorrido. Veja agora a exe- { cada campo para receber o valor que cuçã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 companhia 1 2 3 4 5 6 7 8 9 10 clear para um chope é só mandar um e-mail 11 12 13 14 15 16 17 18 19 20 } para julio.neves@gmail.com. Vou aproveitar 21 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 para reproduza 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 programa ros ou reduza o tamanho da tela, para listará 22 registros e parará para leitura. Informações que 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