Programação Shell LinuxAqui temos um livro livre e completo sobre ShellOs sedentos do "saber livre" são muito benvindos. |
Comandos Shell Script |
||
Home | Artigos | Agradecimentos | Links Amigos | Comprar o livroChangelogs |
Papo de Botequim - Parte 1Papo de Botequim - Parte 2Papo de Botequim - Parte 3Papo de Botequim - Parte 4Papo de Botequim - Parte 5Papo de Botequim - Parte 6Papo de Botequim - Parte 7Papo de Botequim - Parte 8Papo de Botequim - Parte 9Papo de Botequim - Parte 10Papo de Botequim - Parte 11Tira Gosto |
Papo de Botequim - Parte VII- Cumequié rapaz! Derreteu os pensamentos para fazer o scriptizinho que eu te pedi? - É, eu realmente tive de colocar muita pensação na tela preta mas acho que consegui! Bem, pelo menos no testes que fiz a coisa funcionou, mas você tem sempre que botar chifres em cabeça de cachorro! - Não é bem assim, programar em shell é muito fácil, o que vale são as dicas e macetes que não são triviais. As correções que te faço, são justamente para mostrá-los. Mas vamos pedir dois chopes enquanto dou uma olhadela no teu script. - Aê Chico, traz dois. Não esqueça que um é sem colarinho. $ cat restaura
#!/bin/bash
#
# Restaura arquivos deletados via erreeme
#
if [ $# -eq 0 ]
then
echo "Uso: $0 - Peraí, deixa ver se entendi. Primeiramente você coloca na variável Dir a última linha do arquivo cujo nome é formado por /tmp/nome do operador ($LOGNAME)/parâmetro passado com nome do arquivo a ser restaurado ($1). Em seguida o grep -v que você montou exclui a linha em que estava o nome do diretório, isto é, sempre a última e manda o restante do arquivo, que seria assim o arquivo já limpo, para o diretório original e depois remove o arquivo da "lixeira"; S E N S A C I O N A L! Impecável! Zero erro! Viu? você já está pegando as manhas do shell! - Então vamulá chega de lesco-lesco e blá-blá-blá, de que você vai falar hoje? - É tô vendo que o bichinho do Shell te pegou. Que bom, mas vamos ver como se pode (e deve) ler dados e formatar telas e primeiramente vamos entender um comando que te dá todas as ferramentas para você formatar a sua tela de entrada de dados. O comando tputO maior uso deste comando é para posicionar o cursor na tela, mas também é muito usado para apagar dados da tela, saber a quantidade de linhas e colunas para poder posicionar corretamente um campo, apagar um campo cuja crítica detectou como errado. Enfim, quase toda a formatação da tela é feita por este comando.
Uns poucos atributos do comando Na tabela a seguir, apresenta os principais atributos do comando e os efeitos executados sobre o terminal, mas veja bem existem muito mais do que esses, veja só: $ tput it
8
Neste exemplo eu recebi o tamanho inicial da <TAB> ( Initial T ab), mas me diga: para que eu quero saber isso? Se você quiser saber tudo sobre o comando tput (e olha que é coisa que não acaba mais), veja em: http://www.cs.utah.edu/dept/old/texinfo/tput/tput.html#SEC4.
Vamos fazer um programa bem besta (e portanto fácil) para mostrar alguns atributos deste comando. É o famoso e famigerado Alô Mundo só que esta frase será escrita no centro da tela e em vídeo reverso e após isso, o cursor voltará para a posição em que estava antes de escrever esta tão criativa frase. Veja: $ cat alo.sh
#!/bin/bash
# Script bobo para testar
# o comando tput (versao 1)
Colunas=`tput cols` # Salvando quantidade colunas Linhas=`tput lines` # Salvando quantidade linhas Linha=$((Linhas / 2)) # Qual eh a linha do meio da tela? Coluna=$(((Colunas - 9) / 2)) # Centrando a mensagem na tela tput sc # Salvando posicao do cursor tput cup $Linha $Coluna # Posicionando para escrever tput rev # Video reverso echo Alô Mundo tput sgr0 # Restaura video ao normal tput rc # Restaura cursor aa posição original
Como o programa já está todo comentado, acho que a única explicação necessária seria para a linha em que é criada a variável Desta forma este programa somente conseguiria centrar cadeias de 9 caracteres, mas veja isso: $ var=Papo
$ echo ${#var}
4
$ var="Papo de Botequim"
$ echo ${#var}
16
Ahhh, melhorou! Então agora sabemos que a construção $ cat alo.sh
#!/bin/bash
# Script bobo para testar
# o comando tput (versao 2)
Colunas=`tput cols` # Salvando quantidade colunas Linhas=`tput lines` # Salvando quantidade linhas Linha=$((Linhas / 2)) # Qual eh a linha do meio da tela? Coluna=$(((Colunas - ${#1}) / 2)) #Centrando a mensagem na tela tput sc # Salvando posicao do cursor tput cup $Linha $Coluna # Posicionando para escrever tput rev # Video reverso echo $1 tput sgr0 # Restaura video ao normal tput rc # Restaura cursor aa posição original
Este script é igual ao anterior, só que trocamos o valor fixo da versão anterior ( Coluna=`$(((Colunas - ${#*}) / 2))` #Centrando a mensagem na tela
e a linha E agora podemos ler os dados da telaBem a partir de agora vamos aprender tudo sobre leitura, só não posso ensinar a ler cartas e búzios porque se eu soubesse, estaria rico, num pub londrino tomando scotch e não em um boteco desses tomando chope. Mas vamos em frente.
Da última vez que nos encontramos aqui eu já dei uma palinha sobre o comando $ read var1 var2 var3
Papo de Botequim
$ echo $var1
Papo
$ echo $var2
de
$ echo $var3
Botequim
$ read var1 var2
Papo de Botequim
$ echo $var1
Papo
$ echo $var2
de Botequim
Como você viu, o
Eu disse lista separada por espaços em branco? Agora que você já conhece tudo sobre o $ oIFS="$IFS"
$ IFS=:
$ read var1 var2 var3
Papo de Botequim
$ echo $var1
Papo de Botequim
$ echo $var2
$ echo $var3 $ read var1 var2 var3 Papo:de:Botequim $ echo $var1 Papo $ echo $var2 de $ echo $var3 Botequim $ IFS="$oIFS"
Viu, estava furado! O $ grep julio /etc/passwd
julio:x:500:544:Julio C. Neves - 7070:/home/julio:/bin/bash
$ oIFS="$IFS" # Salvando IFS
$ IFS=:
$ grep julio /etc/passwd | read lname lixo uid gid coment home shell
$ echo -e "$lname\n$uid\n$gid\n$coment\n$home\n$shell"
julio
500
544
Julio C. Neves - 7070
/home/julio
/bin/bash
$ IFS="$oIFS" # Restaurando IFS
Como você viu, a saída do
Sob o Bash existem diversas opções do
E agora direto aos exemplos curtos para demonstrar estas opções. Para ler um campo "Matrícula": $ echo -n "Matricula: "; read Mat # -n nao salta linha
Matricula: 12345
$ echo $Mat
12345
Ou simplificando com a opção $ read -p "Matricula: " Mat
Matricula: 12345
$ echo $Mat
12345
Para ler uma determinada quantidade de caracteres: $ read -n5 -p"CEP: " Num ; read -n3 -p- Compl
CEP: 12345-678$
$ echo $Num
12345
$ echo $Compl
678
Neste exemplo fizemos dois Para ler que até um determinado tempo se esgote (conhecido como time out): $ read -t2 -p "Digite seu nome completo: " Nom || echo 'Eta moleza!'
Digite seu nome completo: JEta moleza!
$ echo $Nom
$
Obviamente isto foi uma brincadeira, pois só tinha 3 segundos para digitar o meu nome completo e só me deu tempo de teclar um
Para ler um dado sem ser exibido na tela: $ read -sp "Senha: "
Senha: $ echo $REPLY
segredo :)
Aproveitei um erro para mostrar um macete. Quando escrevi a primeira linha, esqueci de colocar o nome da variável que iria receber a senha, e só notei quando ia listar o seu valor. Felizmente a variável
Mas o exemplo que dei, era para mostrar que a opção Bem, agora que sabemos ler da tela vejamos como se lê os dados dos arquivos. Vamos ler arquivos?
Como eu já havia lhe dito, e você deve se lembrar, o
1 - Redirecionando a entrada do arquivo para o bloco do while read Linha do echo $Linha done < arquivo
2 - Redirecionando a saída de um cat arquivo | while read Linha do echo $Linha done Cada um dos processos tem suas vantagens e desvantagens: Vantagens do primeiro processo:
Desvantagem do primeiro processo:
Vantagem do segundo processo:
Desvantagens do segundo processo:
Para ilustrar o que foi dito, veja estes exemplos a seguir: $ cat readpipe.sh
#!/bin/bash
# readpipe.sh
# Exemplo de read passando arquivo por pipe.
Ultimo="(vazio)" cat $0 | # Passando o arq. do script ($0) p/ while while read Linha do Ultimo="$Linha" echo "-$Ultimo-" done echo "Acabou, Último=:$Ultimo:" Vamos ver sua execução: $ readpipe.sh
-#!/bin/bash-
-# readpipe.sh-
-# Exemplo de read passando arquivo por pipe.-
--
-Ultimo="(vazio)"-
-cat $0 | # Passando o arq. do script ($0) p/ while-
-while read Linha-
-do-
-Ultimo="$Linha"-
-echo "-$Ultimo-"-
-done-
-echo "Acabou, Último=:$Ultimo:"-
Acabou, Último=:(vazio):
Como você viu, o script lista todas as suas próprias linhas com um sinal de menos ( - Ué será que a variável não foi atualizada? - Foi, e isso pode ser comprovado porque a linha - Então porque isso aconteceu? - Por que como eu disse, o bloco de instruções redirecionado pelo pipe ( $ cat redirread.sh
#!/bin/bash
# redirread.sh
# Exemplo de read passando arquivo por pipe.
Ultimo="(vazio)" while read Linha do Ultimo="$Linha" echo "-$Ultimo-" done < $0 # Passando o arq. do script ($0) p/ while echo "Acabou, Último=:$Ultimo:" E veja a sua perfeita execução: $ redirread.sh
-#!/bin/bash-
-# redirread.sh-
-# Exemplo de read passando arquivo por pipe.-
--
-Ultimo="(vazio)"-
-while read Linha-
-do-
-Ultimo="$Linha"-
-echo "-$Ultimo-"-
-done < $0 # Passando o arq. do script ($0) p/ while-
-echo "Acabou, Último=:$Ultimo:"-
Acabou, Último=:echo "Acabou, Último=:$Ultimo:":
Bem amigos da Rede Shell, para finalizar o comando $ seq 30 | xargs -i echo lin {} > numeros # Criando arquivo numeros
$ paste -sd':' numeros # Este paste é para exibir o conteúdo sem ser um
#+ por linha, usando dois-pontos como separador
lin 1:lin 2:lin 3:lin 4:lin 5:lin 6:lin 7:lin 8:lin 9:lin 10:lin 11:lin 12:lin 13:lin 14:lin 15:l
in 16:lin 17:lin 18:lin 19:lin 20:lin 21:lin 22:lin 23:lin 24:lin 25:lin 26:lin 27:lin 28:lin 29:
lin 30
$ cat 10porpag.sh
#!/bin/bash
# Prg de teste para escrever
# 10 linhas e parar para ler
# Versão 1
while read Num do let ContLin++ # Contando... echo -n "$Num " # -n para nao saltar linha ((ContLin % 10)) > /dev/null || read done < numeros
Na tentativa de fazer um programa genérico criamos a variável $ 10porpag.sh
lin 1 lin 2 lin 3 lin 4 lin 5 lin 6 lin 7 lin 8 lin 9 lin 10 lin 12 lin 13 lin 14 lin 15 lin 16 l
in 17 lin 18 lin 19 lin 20 lin 21 lin 23 lin 24 lin 25 lin 26 lin 27 lin 28 lin 29 lin 30 $
Repare que faltou a linha Vamos mostrar então como deveria ficar para funcionar a contento: $ cat 10porpag.sh
#!/bin/bash
# Prg de teste para escrever
# 10 linhas e parar para ler
# Versão 2
while read Num do let ContLin++ # Contando... echo -n "$Num " # -n para nao saltar linha ((ContLin % 10)) > /dev/null || read < /dev/tty done < numeros
Observe que agora a entrada do Veja agora a sua execução: $ 10porpag.sh
lin 1 lin 2 lin 3 lin 4 lin 5 lin 6 lin 7 lin 8 lin 9 lin 10
lin 11 lin 12 lin 13 lin 14 lin 15 lin 16 lin 17 lin 18 lin 19 lin 20
lin 21 lin 22 lin 23 lin 24 lin 25 lin 26 lin 27 lin 28 lin 29 lin 30
Isto está quase bom mas falta um pouco para ficar excelente. Vamos melhorar um pouco o exemplo para que você o reproduza e teste (mas antes de testar aumente o número de registros de $ cat 10porpag.sh
#!/bin/bash
# Prg de teste para escrever
# 10 linhas e parar para ler
# Versão 3
clear while read Num do ((ContLin++)) # Contando... echo "$Num" ((ContLin % (`tput lines` - 3))) || { read -n1 -p"Tecle Algo " < /dev/tty # para ler qq caractere clear # limpa a tela apos leitura } done < numeros
A mudança substancial feita neste exemplo é com relação à quebra de página, já que ela é feita a cada quantidade-de-linhas-da-tela ( - Bem meu amigo, por hoje é só porque acho que você já está de saco cheio... - Num tô não, pode continuar... - Se você não estiver eu estou... Mas já que você está tão empolgado com o Shell, vou te deixar um exercício de apredizagem para você melhorar a sua CDteca que é bastante simples. Reescreva o seu programa que cadastra CDs para montar toda a tela com um único Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para mim. Valeu! -- JarbasJunior - 20 Oct 2005 |
||||||||||||||||||||||||||||||||||||||||||||||||||
Licença Creative Commons - Atribuição e Não Comercial (CC) 2009 Pelos Frequentadores do Bar do Júlio Neves. Todo o conteúdo desta página pode ser utilizado segundo os termos da Creative Commons License: Atribuição-UsoNãoComercial-PermanênciaDaLicença. |