Shell - Julio Neves

download Shell - Julio Neves

of 115

Transcript of Shell - Julio Neves

Julio Neves

Incio

agenda

blog

english

espaol

news

pager Feeds: Posts

Pesquisa

J ULIO N EVESRio de Janeiro Shell Script Blog

Comentrios

Papo de Botequim Parte 1maro 5, 2008 por jneves S T

outubro 2011 Q Q S S 1 3 10 17 24 31 mar 4 11 18 25 5 12 19 26 6 13 20 27 7 14 21 28 8 15 22 29 D 2 9 16 23 30

Este blog contm um livro completo de Shell que escrevi para 12 fascculos da Linux Magazine.

ARQUIVOSmaro 2008

TPICOS RECENTESPapo de Botequim Parte 1 Papo de Botequim Parte 2 Papo de Botequim Parte 3 Papo de Botequim Parte 4 Papo de Botequim Parte 5

Dilogo entreouvido entre um Linuxer e em empurrador de mouse: O Ambiente Linux O Ambiente Shell Uma Rapidinha nos Principais Sabores de Shell Bourne Shell (sh) Korn Shell (ksh) Boune Again Shell (bash) C Shell (csh)

CATEGORIASShell

PGINASagenda blog english espaol

Follow

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesnews Follow Julio Neves pager

Explicando o funcionamento do Shell Exame da Linha de Comandos Atribuio Comando Resoluo de Redirecionamentos Substituio de Variveis Substituio de Meta Caracteres Passa Linha de Comando para o kernel Decifrando a Pedra da Roseta Caracteres para remoo do significado Apstrofo ou plic () Contrabarra ou Barra Invertida () Aspas () Caracteres de redirecionamento Redirecionamento da Sada Padro Redirecionamento da Sada de Erro Padro Redirecionamento da Entrada Padro Here Document Redirecionamento de Comandos Caracteres de Ambiente

Get every new post delivered to your Inbox.

BLOG STATS

37,992 hits Enter email addressSign me up!

Powered by WordPress.com

Dilogo entreouvido entre um Linuxer e em empurrador de mouse:- Quem o Bash? - O Bash o filho mais novo da famlia Shell. - P cara! Ests a fim de me deixar maluco? Eu tinha uma dvida e voc me deixa com duas! - No, maluco voc j h muito tempo. Desde que se decidiu a usar aquele sistema operacional que voc tem que dar dez boots por dia e no tem domnio nenhum sobre o que esta acontecendo no seu computador. Mas deixa isso pr l, vou te explicar o que Shell e os componentes de sua famlia e ao final da explanao voc dir: Meu Deus do Shell! Porque eu no optei pelo Linux antes?.

O Ambiente LinuxPara voc entender o que e como funciona o Shell, primeiro vou te mostrar como funciona o ambiente em camadas do Linux. D uma olhada no grfico abaixo:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

Neste grfico d para ver que a camada de hardware a mais profunda e formada pelos componentes fsicos do seu computador. Envolvendo esta, vem a camada do kernel que o cerne do Linux, seu ncleo, e quem bota o hardware para funcionar, fazendo seu gerenciamento e controle. Os programas e comandos que envolvem o kernel, dele se utilizam para realizar as tarefas aplicativas para que foram desenvolvidos. Fechando tudo isso vem o Shell que leva este nome porque em ingls, Shell significa concha, carapaa, isto , fica entre o usurio e o sistema operacional, de forma que tudo que interage com o sistema operacional, tem que passar pelo seu crivo.

O Ambiente ShellBom j que para chegar ao ncleo do Linux, no seu kernel que o que interessa a todo aplicativo, necessria a filtragem do Shell, vamos entender como ele funciona de forma a tirar o mximo proveito das inmeras facilidades que ele nos oferece. O Linux por definio um sistema multiusurio no podemos nunca esquecer disto e para permitir o acesso de determinados usurios e barrar a entrada de outros, existe um arquivo chamado /etc/passwd que alm fornecer dados para esta funo de leo-de-chcara do Linux, tambm prov informaes para o login daqueles que passaram por esta primeira barreira. O ltimo campo de seus registros informa ao sistema qual Shell a pessoa vai receber ao se logar (ARGH!!!). Quando eu disse que o ltimo campo do/etc/passwd

informa ao sistema qual o Shell

que o usurio vai receber ao se logar, para ser interpretado ao p-da-letra, isto , se neste campo do seu registro estiver prog , a pessoa ao acessar o sistema receber a tela de execuo do programa prog e ao terminar a sua execuo ganhar imediatamente um logout. Imagine o quanto se pode incrementar a segurana com este simples artifcio. http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

Lembra que eu te falei de Shell, famlia, irmo? Pois , vamos comear a entender isto: o Shell, que se vale da imagem de uma concha envolvendo o sistema operacional propriamente dito, o nome genrico para tratar os filhos desta idia que, ao longo dos anos de existncia do sistema operacional Unix foram aparecendo. Atualmente existem diversos sabores de Shell, dentre estes eu destaco o sh (Bourne Shell), o ksh (Korn Shell), bash (Bourne Again Shell) e o csh (C Shell).

Uma Rapidinha nos Principais Sabores de ShellBourne Shell (sh)Desenvolvido por Stephen Bourne da Bell Labs (da AT&T onde tambm foi desenvolvido o Unix), este foi durante muitos anos o Shell default do sistema operacional Unix. tambm chamado de Standard Shell por ter sido durante vrios anos o nico e at hoje o mais utilizado at porque ele foi portado para todos os ambientes Unix e distros Linux.

Korn Shell (ksh)Desenvolvido por David Korn, tambm da Bell Labs, um superset do sh, isto , possui todas as facilidades do sh e a elas agregou muitas outras. A compatibilidade total com o sh vem trazendo muitos usurios e programadores de Shell para este ambiente.

Boune Again Shell (bash)Este o Shell mais moderno e cujo nmero de adeptos mais cresce em todo o mundo, seja por ser o Shell default do Linux, seu sistema operacional hospedeiro, seja por sua grande diversidade de comandos, que incorpora inclusive diversos instrues caractersticas do C Shell.

C Shell (csh)Desenvolvido por Bill Joy da Berkley University o Shell mais utilizado em ambientes *BSD e Xenix. A estruturao de seus comandos bem similar da linguagem C. Seu grande pecado foi ignorar a compatibilidade com o sh, partindo por um caminho prprio. Alm destes Shells existem outros, mas irei falar contigo somente sobre os trs primeiros, tratando-os genericamente por Shell e assinalando as especificidades de cada um que porventura hajam.

Explicando o funcionamento do ShellO Shell o primeiro programa que voc ganha ao se logar no Linux. ele que vai resolver um monte de coisas de forma a no onerar o kernel com tarefas repetitivas, aliviando-o para tratar assuntos mais nobres. Como cada usurio possui o seu prprio Shell interpondo-se entre ele e o Linux, o Shell quem interpreta os comandos que so teclados e examina as suas sintaxes, passando-os esmiuados para execuo. - pa! Esse negcio de interpreta comando no tem nada a haver com interpretador no, n? - Tem sim, na verdade o Shell um interpretador (ou ser intrprete) que traz http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves consigo uma poderosa linguagem com comandos de alto nvel, que permite construo de loops (laos), de tomadas de deciso e de armazenamento de valores em variveis, como vou te mostrar. Vou te explicar as principais tarefas que o Shell cumpre, na sua ordem de execuo. Preste ateno nesta ordem porque ela fundamental para o entendimento do resto do nosso bate papo.

Exame da Linha de ComandosNeste exame o Shell identifica os caracteres especiais (reservados) que tm significado para interpretao da linha, logo aps verifica se a linha passada uma atribuio ou um comando. Atribuio Se o Shell encontra dois campos separados por um sinal de igual ( = ) sem espaos em branco entre eles, identifica esta seqncia como uma atribuio. Exemplos$ ls linux linux

Neste exemplo o Shell identificou o ls como um programa e o linux como um parmetro passado para o programa ls .$ valor=1000

Neste caso, por no haver espaos em branco (j d para notar que o branco um dos caracteres reservados) o Shell identificou uma atribuio e colocou 1000 na varivel valor .

Jamais Faa:$ valor = 1000 bash: valor: not found

Neste caso, o Bash achou a palavra valor isolada por brancos e julgou que voc estivesse mandando executar um programa chamado valor, para o qual estaria passando dois parmetros: = e 1000 .

Comando Quando uma linha digitada no prompt do Linux, ela dividida em pedaos separados por espao em branco: o primeiro pedao o nome do programa que ter sua existncia pesquisada; identifica em seguida, nesta ordem, opes/parmetros, redirecionamentos e variveis. Quando o programa identificado existe, o Shell verifica as permisses dos arquivos envolvidos (inclusive o prprio programa), dando um erro caso voc no esteja credenciado a executar esta tarefa.

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio NevesResoluo de Redirecionamentos

Aps identificar os componentes da linha que voc teclou, o Shell parte para a resoluo de redirecionamentos. O Shell tem incorporado ao seu elenco de vantagens o que chamamos de redirecionamento, que pode ser de entrada ( stdin ), de sada ( stdout ) ou dos erros ( stderr ), conforme vou te explicar a seguir.Substituio de Variveis

Neste ponto, o Shell verifica se as eventuais variveis (parmetros comeados por$ ),

encontradas no escopo do comando, esto definidas e as substitui por seus

valores atuais.Substituio de Meta Caracteres

Se algum metacaractere ( * , ? ou [] ) foi encontrado na linha de comando, neste ponto ele ser substitudo por seus possveis valores. Supondo que o nico arquivo no seu diretrio corrente comeado pela letra n seja um diretrio chamadonomegrandeprachuchu ,

se voc fizer:

$ cd n*

Como at aqui quem esta trabalhando a sua linha o Shell e o comando (programa) cd ainda no foi executado, o Shell transforma o n* emnomegrandeprachuchu

e o comando cd ser executado com sucesso.

Passa Linha de Comando para o kernel

Completadas as tarefas anteriores, o Shell monta a linha de comandos, j com todas as substituies feitas, chama o kernel para execut-la em um novo Shell (Shell filho), ganhando um nmero de processo (PID ou P rocess ID entification) e permanece inativo, tirando uma soneca, durante a execuo do programa. Uma vez encerrado este processo (juntamente com o Shell filho), recebe novamente o controle e, exibindo um prompt, mostra que est pronto para executar outros comandos.

Decifrando a Pedra da RosetaPara tirar aquela sensao que voc tem quando v um script Shell, que mais parece uma sopa de letrinhas ou um hierglifo vou lhe mostrar os principais caracteres especiais para que voc saia por ai como o Jean-Franois Champollion decifrando a Pedra da Roseta (d uma googlada para descobrir quem este cara, acho que vale a pena).

Caracteres para remoo do significado isso mesmo, quando no desejamos que o Shell interprete um caractere especial, devemos escond-lo dele. Isso pode ser feito de trs formas distintas: Apstrofo ou plic ( ' ) Quando o Shell v uma cadeia de caracteres entre apstrofos ( ' ), ele tira os apstrofos da cadeia e no interpreta seu contedo.$ ls linux* linuxmagazine $ ls linux*

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesbash: linux* no such file or directory

No primeiro caso o Shell expandiu o asterisco e descobriu o arquivo linuxmagazine para listar. No segundo, os apstrofos inibiram a interpretao do Shell e veio a resposta que no existe o arquivo linux* . Contrabarra ou Barra Invertida () Idntico aos apstrofos exceto que a barra invertida inibe a interpretao somente do caractere que a segue. Suponha que voc acidentalmente tenha criado um arquivo chamado * (asterisco) que alguns sabores de Unix permitem e deseja remov-lo. Se voc fizesse:$ rm *

Voc estaria fazendo a maior encrenca, pois o rm removeria todos os arquivos do diretrio corrente. A melhor forma de fazer o pretendido :$ rm *

Desta forma, o Shell no interpretaria o asterisco, e em conseqncia no faria a sua expanso. Faa a seguinte experincia cientfica:$ cd /etc $ echo * $ echo * $ echo *

Viu a diferena? Ento no precisa explicar mais. Aspas ( " ) Exatamente igual ao apstrofo exceto que, se a cadeia entre aspas contiver um cifro ( $ ), uma crase ( ` ), ou uma barra invertida (), estes caracteres sero interpretados pelo Shell. No precisa se estressar, eu no te dei exemplos do uso das aspas por que voc ainda no conhece o cifro ( $ ) nem a crase ( ` ). Daqui para frente veremos com muita constncia o uso destes caracteres especiais, o mais importante entender o significado de cada um.

Caracteres de redirecionamentoA maioria dos comandos tem uma entrada, uma sada e pode gerar erros. Esta entrada chamada Entrada Padro ou stdin e seu default o teclado do terminal. Analogamente, a sada do comando chamada Sada Padro ou stdout e seu default a tela do terminal. Para a tela tambm so enviadas por default as mensagens de erro oriundas do comando que neste caso a chamada Sada de Erro Padro ou stderr . Veremos agora como alterar este estado de coisas. Vamos fazer um programa gago. Para isto faa:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves$ cat

O cat uma instruo que lista o contedo do arquivo especificado para a Sada Padro ( stdout ). Caso a entrada no seja definida, ele espera os dados da stdin . Ora como eu no especifiquei a entrada, ele est esperando-a pelo teclado (Entrada Padro) e como tambm no citei a sada, o que eu teclar ir para a tela (Sada Padro) fazendo desta forma, como eu havia proposto um programa gago. Experimente! Redirecionamento da Sada Padro Para especificarmos a sada de um programa usamos o > (maior que) ou o >> (maior, maior) seguido do nome do arquivo para o qual se deseja mandar a sada. Vamos transformar o programa gago em um editor de textos (que pretenso heim!).$ cat > Arq

O cat continua sem ter a entrada especificada, portanto est aguardando que os dados sejam teclados, porm a sua sada est sendo desviada para o arquivo Arq . Assim sendo, tudo que esta sendo teclado esta indo para dentro de Arq , de forma que fizemos o editor de textos mais curto e ruim do planeta. Se eu fizer novamente:$ cat > Arq

Os dados contidos em Arq sero perdidos, j que antes do redirecionamento o Shell criar um Arq vazio. Para colocar mais informaes no final do arquivo eu deveria ter feito:$ cat >> Arq

Como j havia lhe dito, o Shell resolve a linha e depois manda o comando para a execuo. Assim, se voc redirecionar a sada de um arquivo para ele prprio, primeiramente o Shell esvazia este arquivo e depois manda o comando para execuo, desta forma voc acabou de perder o contedo do seu querido arquivo. Com isso d para notar que o >> (maior maior) serve para inserir texto no final do arquivo. Redirecionamento da Sada de Erro Padro Assim como o default do Shell receber os dados do teclado e mandar as sadas para a tela, os erros tambm sero enviados para a tela se voc no especificar para onde devero ser enviados. Para redirecionar os erros use 2> SaidaDeErro . Note que entre o nmero 2 e o sinal de maior ( > ) no existe espao em branco.

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Preste ateno! No confunda >> com 2> . O primeiro anexa dados ao final de um arquivo, e o segundo redireciona a Sada de Erro Padro ( stderr ) para um arquivo que est sendo designado. Isso importante!

Suponha que durante a execuo de um script voc pode, ou no (dependendo do rumo tomado pela execuo do programa), ter criado um arquivo chamado/tmp/seraqueexiste$$ .

Para no ficar sujeira no seu disco, ao final do script voc

colocaria uma linha:$ rm /tmp/seraqueexiste$$

Caso o arquivo no existisse seria enviado para a tela uma mensagem de erro. Para que isso no acontea deve-se fazer:$ rm /tmp/seraqueexiste$$ 2> /dev/null

Sobre o exemplo que acabamos de ver tenho duas dicas a dar: Dica # 1 O $$ contm o PID, isto , o nmero do seu processo. Como o Linux multiusurio, bom anexar sempre o $$ ao nome dos dos arquivos que sero usados por vrias pessoas para no haver problema de propriedade, isto , caso voc batizasse o seu arquivo simplesmente como seraqueexiste , o primeiro que o usasse (criando-o ento) seria o seu dono e todos os outros ganhariam um erro quando tentassem gravar algo nele. Para que voc teste a Sada de Erro Padro direto no prompt do seu Shell, vou dar mais um exemplo. Faa:$ ls naoexiste bash: naoexiste no such file or directory $ ls naoexiste 2> arquivodeerros $ $ cat arquivodeerros bash: naoexiste no such file or directory

Neste exemplo, vimos que quando fizemos um ls em naoexiste , ganhamos uma mensagem de erro. Aps, redirecionarmos a Sada de Erro Padro paraarquivodeerros

e executarmos o mesmo comando, recebemos somente o prompt

na tela. Quando listamos o contedo do arquivo para o qual foi redirecionada a Sada de Erro Padro, vimos que a mensagem de erro tinha sido armazenada nele. Faa este teste ai. Dica # 2 Quem esse tal de /dev/null ?Em Unix existe um arquivo fantasma. Chama-

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

se /dev/null . Tudo que mandado para este arquivo some. Assemelha-se a um Buraco Negro. No caso do exemplo, como no me interessava guardar a possvel mensagem de erro oriunda do comando rm , redirecionei-a para este arquivo. interessante notar que estes caracteres de redirecionamento so cumulativos, isto , se no exemplo anterior fizssemos:$ ls naoexiste 2>> arquivodeerros

a mensagem de erro oriunda do ls seria anexada ao final de arquivodeerros . Redirecionamento da Entrada Padro Para fazermos o redirecionamento da Entrada Padro usamos o < (menor que). - E pr que serve isso? voc vai me perguntar. - Deixa eu te dar um exemplo que voc vai entender rapidinho. Suponha que voc queira mandar um mail para o seu chefe. Para o chefe ns caprichamos, n? ento ao invs de sair redigindo o mail direto no prompt da tela de forma a tornar impossvel a correo de uma frase anterior onde, sem querer, escreveu um ns vai, voc edita um arquivo com o contedo da mensagem e aps umas quinze verificaes sem constatar nenhum erro, decide envi-lo e para tal faz:$ mail chefe < arquivocommailparaochefe

O teu chefe ento receber o contedo do arquivocommailparaochefe . Here Document Um outro tipo de redirecionamento muito louco que o Shell te permite o chamado here document. Ele representado por ai vai uma listagem dos arquivos > do diretorio: > ls l

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves> Abracos a todos. > FIM

Finalmente agora temos conhecimento para mostrar o que havamos conversado sobre here document. Os comandos entre crases ( ` ) sero priorizados e portanto o Shell os executar antes da instruo mail . Quando o suporte receber o e-mail, ver que os comandos date e ls foram executados imediatamente antes do comando mail , recebendo ento uma fotografia do ambiente no momento em que a correspondncia foi enviada. O prompt primrio default do Shell, como vimos, o cifro ( $ ), porm o Shell usa o conceito de prompt secundrio, ou de continuao de comando, que enviado para a tela quando h uma quebra de linha e a instruo no terminou. Esse prompt, representado por um sinal de maior ( > ), que vemos precedendo a partir da 2 linha do exemplo. Para finalizar e bagunar tudo, devo dizer que existe uma construo mais moderna que vem sendo utilizada como forma de priorizao de execuo de comandos, tal qual as crases ( ` ). So as construes do tipo $(cmd) , onde cmd um (ou vrios) comando que ser(o) executado(s) com prioridade em seu contexto. Assim sendo, o uso de crases ( ` ) ou construes do tipo $(cmd) servem para o mesmo fim, porm para quem trabalha com sistemas operacionais de diversos fornecedores (multiplataforma), aconselho o uso das crases, j que o $(cmd) no foi portado para todos os sabores de Shell. Aqui dentro do Botequim, usarei ambas as formas, indistintamente. Vejamos novamente o exemplo dado para as crases sob esta nova tica:$ echo Existem $(who | wc -l) usurios conectados Existem 8 usurios conectados

Veja s este caso:$ Arqs=ls $ echo $Arqs ls

Neste exemplo eu fiz uma atribuio ( = ) e executei uma instruo. O que eu queria era que a varivel $Arqs , recebesse a sada do comando ls . Como as instrues de um script so interpretadas de cima para baixo e da esquerda para a direita, a atribuio foi feita antes da execuo do ls . Para fazer o que desejamos necessrio que eu priorize a execuo deste comando em detrimento da atribuio e isto pode ser feito de qualquer uma das maneiras a seguir:$ Arqs=`ls`

ou:$ Arqs=$(ls)

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Para encerrar este assunto vamos ver s mais um exemplo. Digamos que eu queira colocar dentro da varivel $Arqs a listagem longa ( ls -l ) de todos os arquivos comeados por arq e seguidos de um nico caractere ( ? ). Eu deveria fazer:$ Arqs=$(ls -l arq?)

ou:$ Arqs=`ls -l arq?`

Mas veja:$ echo $Arqs -rw-rr 1 jneves jneves 19 May 24 19:41 arq1 -rw-rr 1 jneves jneves 23 May 24 19:43 arq2 -rw-rr 1 jneves jneves 1866 Jan 22 2003 arql

- P, saiu tudo embolado! - Pois cara, como eu j te disse, se voc deixar o Shell ver os espaos em branco, sempre que houver diversos espaos juntos, eles sero trocados por apenas um. Para que a listagem saia bonitinha, necessrio proteger a varivel da interpretao do Shell, assim:$ echo $Arqs -rw-rr -rw-rr -rw-rr 1 jneves 1 jneves 1 jneves jneves jneves jneves 19 May 24 19:41 arq1 23 May 24 19:43 arq2 1866 Jan 22 2003 arql

- Olhe, amigo, v treinando esses exemplos, porque, quando nos encontrarmos novamente, vou lhe explicar uma srie de instrues tpicas de programao Shell. Tchau! Ahh! S mais uma coisinha que eu ia esquecendo de lhe dizer. Em Shell, o jogo da velha ( # ) usado quando desejamos fazer um comentrio.

$ exit # pede a conta ao garcon

Vou aproveitar tambm para mandar o meu jab: diga para os amigos que quem estiver afim de fazer um curso porreta de programao em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dvida ou falta de companhia para um chope ou at para falar mal dos polticos s mandar um e-mail para mim. Valeu!Publicado em Shell | Tagged >>, 2>, bash, Bourne, C Shell, cat, cd, csh, ftp, kernel, Korn, ksh, labels, PID, rm, sh | Deixar um comentrio

Papo de Botequim Parte 2http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesmaro 5, 2008 por jneves

Eu fico com o grep, voc com a gripe A famlia grep Vamos Montar uma cdteca Passando parmetros Macetes paramtricos - Garom! Traz um chops e dois pastel. O meu amigo hoje no vai beber por que ele finalmente est sendo apresentado a um verdadeiro sistema operacional e ainda tem muita coisa a aprender! - E ento, amigo, t entendendo tudo que te expliquei at agora? - Entendendo eu t, mas no vi nada prtico nisso - Calma rapaz, o que te falei at agora, serve como base ao que h de vir daqui pra frente. Vamos usar estas ferramentas que vimos para montar programas estruturados, que o Shell permite. Voc ver porque at na TV j teve programa chamado O Shell o Limite. - Para comear vamos falar dos comandos da famlia grep . - grep ? No conheo nenhum termo em ingls com este nome - claro, grep um acrnimo Global Regular Expression Print, que usa expresses regulares para pesquisar a ocorrncia de cadeias de caracteres na entrada definida (se bem que h uma lenda sobre como este comando foi nomeado: no editor de textos ed, o av do vim, o comando usado para buscas era g/_expressao regular_/p, ou no ingls g/_re_/p.). Por falar em expresses regulares (ou regexp), o Aurlio Marinho Jargas tem todas as dicas em sua pgina (inclusive tutorias) que abordam o tema. Se voc est mesmo a fim de aprender a programar em Shell, Perl, Python, Acho bom voc ler estes artigos para te ajudar no que est para vir.

Eu fico com o grep , voc com a gripeEsse negcio de gripe brincadeira! s um pretexto para pedir umas caipirinhas. Mas voltando vaca fria, eu te falei que o grep procura cadeia de caracteres dentro de uma entrada definida, mas o que vem a ser uma entrada definida? Bem, existem vrias formas de definir a entrada do comando grep . Vejamos: Pesquisando em um arquivo:$ grep rafael /etc/passwd

Pesquisando em vrios arquivos:$ grep grep *.sh

Pesquisando na saida de comando:$ who | grep Pelegrino

No 1 exemplo, o mais simples, procurei a palavra rafael em qualquer lugar do arquivo /etc/passwd . Se quisesse procur-la como um login name, isto , somente

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves no incio dos registros deste arquivo, eu deveria fazer:$ grep ^rafael /etc/passwd

E para que serve este circunflexo e os apstrofos, voc vai me perguntar. O circunflexo ( ^ ), se voc tivesse lido os artigos anteriores sobre expresses regulares que te falei, saberia que servem para limitar a pesquisa ao incio de cada linha, e os apstrofos ( ' ) servem para o Shell no interpretar este circunflexo, deixando-o passar inclume para o comando grep . Olha que legal! O grep aceita como entrada, a sada de outro comando redirecionado por um pipe (isto muito comum em Shell e um tremendo acelerador de execuo de comando j que atua como se a sada de um programa fosse guardada em disco e o segundo programa lesse este arquivo gerado), desta forma, no 3 exemplo, o comando who listou as pessoas logadas na mesma mquina que voc (no se esquea jamais: o Linux multiusurio) e o grep foi usado para verificar se o Pelegrino estava trabalhando ou coando.

A famlia grepEste comando grep muito conhecido, pois usado com muita freqncia, o que muitas pessoas desconhecem que existem trs comandos na famlia grep , que so:grep egrep fgrep

A principais caractersticas diferenciais entre os 3 so: O grep pode ou no usar expresses regulares simples, porm no caso de no us-las, o fgrep melhor, por ser mais rpido; O egrep (e de extended, extendido) muito poderoso no uso de expresses regulares. Por ser o mais lento da famlia, s deve ser usado quando for necessria a elaborao de uma expresso regular no aceita pelo grep ; O fgrep (f de fast, rpido, ou de file, arquivo) como o nome diz o rapidinho da famlia, executa o servio de forma muito veloz (por vezes cerca de 30% mais veloz que o grep e 50% mais que o egrep), porm no permite o uso de expresses regulares na pesquisa. Tudo que foi dito acima sobre velocidade, s se aplica famlia de comandos grep do Unix. No Linux o grep sempre mais veloz, j que os outros dois ( fgrep e egrep ) so scripts em Shell que chamam o primeiro e, j vou adiantando, no gosto nem um pouquinho desta soluo.

- Agora que voc j conhece as diferenas entre os membros da famlia, me diga: o que voc acha dos trs exemplos que eu dei antes das explicaes? - Eu achei que o fgrep resolveria o teu problema de forma mais veloz do que o

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesgrep .

- Perfeito! T vendo que voc est atento! Est entendendo tudo que estou te explicando! Ento vamos ver mais exemplos para clarear de vez as diferenas de uso dos membros da famlia. Exemplos Eu sei que em um arquivo existe um texto falando sobre Linux s no tenho certeza se est escrito com L maisculo ou l minsculo. Posso fazer de duas formas:$ egrep (Linux | linux) arquivo.txt

ou$ grep [Ll]inux arquivo.txt

No primeiro caso, a expresso regular complexa "(Linux | linux)" usa os parnteses para agrupar as opes e a barra vertical ( | ) como um ou lgico, isto , estou procurando Linux ou linux . No segundo, a expresso regular [Ll]inux significa: comeado por L ou l seguido de inux . Por esta expresso ser mais simples, o grep consegue resolv-la, portanto acho melhor usar a segunda forma, j que o egrep tornaria a pesquisa mais lenta. Outro exemplo. Para listar todos os subdiretrios do diretrio corrente, basta:$ ls -l | grep ^d drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxrwxr-x drwxrwxr-x drwxrwxr-x drwxr-xr-x drwxrwxr-x drwxr-xr-x 3 root 11 root 3 root 3 root 2 root 14 root 12 root 3 root 3 root 3 root 3 root root root root root root root root root root root root 4096 Dec 18 2000 doc

4096 Jul 13 18:58 freeciv 4096 Oct 17 4096 Aug 4096 Aug 8 8 2000 gimp 2000 gnome 2000 idl

4096 Jul 13 18:58 locale 4096 Jan 14 4096 Jan 17 4096 Jul 2000 lyx 2000 pixmaps

2 20:30 scribus 2000 sounds 2000 xine

4096 Jan 17 4096 Dec 18

No exemplo que acabamos de ver, o circunflexo ( ^ ) serviu para limitar a pesquisa primeira posio da sada do ls longo. Os apstrofos foram colocados para o Shell no ver o circunflexo ( ^ ). Vamos ver mais um. Sabemos que as quatro primeiras posies possveis de umls -l

de um arquivo comum (arquivo comum! No diretrio, nem link, nem )

devem ser: Posio Valores Possveis 1 2 3r w - s

4x

(suid)-

Assim sendo, para descobrir todos os arquivos executveis em um determinado

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves diretrio eu deveria fazer:$ ls -la | egrep ^-..(x|s) -rwxr-xr-x -rwxr-xr-x -rwxr-xr-x 1 root 1 root 1 root root root root 2875 Jun 18 19:38 rc 857 Aug 18453 Jul 9 22:03 rc.local 6 17:28 rc.sysinit

Onde novamente usamos o circunflexo ( ^ ) para limitar a pesquisa ao incio de cada linha, ento as linhas listadas sero as que comeam por um trao ( - ), seguido de qualquer coisa (o ponto quando usado como uma expresso regular significa qualquer coisa), novamente seguido de qualquer coisa, vindo a seguir umx

ou um s .

Obteramos o mesmo resultado se fizssemos:$ ls -la | grep ^-..[xs]

e agilizaramos a pesquisa.

Vamos Montar uma cdtecaVamos comear a desenvolver programas, acho que a montagem de um banco de dados de msicas bacana para efeito didtico (e til nesses tempos de downloads de mp3 e queimadores de CDs). No se esquea que, da mesma forma que vamos desenvolver um monte de programas para organizar os seus CDs de msica, com pequenas adaptaes, voc pode fazer o mesmo com os CDs de software que vm com a Linux Magazine e outros que voc compra ou queima, disponibilizando este banco de software para todos que trabalham com voc (o Linux multiusurio, e como tal deve ser explorado), desta forma ganhando muitos pontos com seu adorado chefe. - Pra ai! De onde eu vou receber os dados dos CDs? - Inicialmente, vou lhe mostrar como o seu programa pode receber parmetros de quem o estiver executando e em breve, ensinarei a ler os dados pela tela ou de um arquivo.

Passando parmetrosO layout do arquivo musicas ser o seguinte:nome do lbum^intrprete1~nome da msica1:..:intrprete~nome da msica

isto , o nome do lbum ser separado por um circunflexo ( ^ ) do resto do registro, que formado por diversos grupos compostos pelo intrprete de cada msica do CD e a respectiva msica interpretada. Estes grupos so separados entre si por dois-pontos ( : ) e internamente, o intrprete ser separado por um til ( ~ ) do nome da msica. Eu quero escrever um programa que chamado musinc , que incluir registros no meu arquivo musicas. Eu passarei o contedo de cada lbum como parmetro na chamada do programa fazendo assim:$ musinc lbum^interprete~musica:interprete~musica:

Desta forma o programa musinc estar recebendo os dados de cada lbum como se

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves fosse uma varivel. A nica diferena entre um parmetro recebido e uma varivel que os primeiros recebem nomes numricos (nome numrico fica muito esquisito, n? O que quis dizer que seus nomes so formados por um e somente um algarismo), isto $1, $2, $3, ..., $9 . Vamos, antes de tudo, fazer um teste: Exemplos$ cat teste #!/bin/bash # Programa para testar passagem de parametros echo 1o. parm -> $1 echo 2o. parm -> $2 echo 3o. parm -> $3

Vamos execut-lo:$ teste passando parametros para testar bash: teste: cannot execute

Ops! Esqueci-me de torn-lo executvel. Vou faz-lo de forma a permitir que todos possam execut-lo e em seguida vou test-lo:$ chmod 755 teste $ teste passando parametros para testar 1o. parm -> passando 2o. parm -> parametros 3o. parm -> para

Repare que a palavra testar , que seria o quarto parmetro, no foi listada. Isto deu-se justamente porque o programa teste s listava os trs primeiros parmetros. Vamos execut-lo de outra forma:$ teste passando parametros para testar 1o. parm -> passando parametros 2o. parm -> para 3o. parm -> testar

As aspas no deixaram o Shell ver o espao em branco entre as palavras e considerou-as um nico parmetro.

Macetes paramtricosJ que estamos falando em passagem de parmetros deixa eu te dar mais umas dicas: Significado das Principais Variveis Referentes aos Parmetros Varivel Significado$0 $# $*

Contm o nome do programa Contm a quantidade de parmetros passados Contm o conjunto de todos os parmetros (muito parecido com $@ )

Exemplos Vamos alterar o programa teste para usar as variveis que acabamos de ver.

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Vamos faz-lo assim:$ cat teste #!/bin/bash # Programa para testar passagem de parametros (2a. Versao) echo O programa $0 recebeu $# parametros echo 1o. parm -> $1 echo 2o. parm -> $2 echo 3o. parm -> $3 echo Todos de uma s tacada: $*

Repare que antes das aspas eu usei uma barra invertida para o escond-las da interpretao do Shell (se no usasse as contrabarras as aspas no apareceriam). Vamos execut-lo:$ teste passando parametros para testar O programa teste recebeu 4 parametros 1o. parm -> passando 2o. parm -> parametros 3o. parm -> para Todos de uma s tacada: passando parametros para testar

Conforme eu disse, os parmetros recebem nmeros de 1 a 9 , mas isso no significa que no posso usar mais de 9 parmetros significa somente que s posso enderear 9. Vamos testar isso: Exemplo:$ cat teste #!/bin/bash # Programa para testar passagem de parametros (3a. Versao) echo O programa $0 recebeu $# parametros echo 11o. parm -> $11 shift echo 2o. parm -> $1 shift 2 echo 4o. Parm -> $1

Vamos execut-lo:$ teste passando parametros para testar O programa teste recebeu 4 parametros que so: 11o. parm -> passando1 2o. parm -> parametros 4o. parm -> testar

Duas coisas muito interessantes neste script: 1. Para mostrar que os nomes dos parmetros variam de $1 a $9 eu fiz um echo $11 e o que aconteceu? O Shell interpretou como sendo $1 seguido do algarismo 1 e listou passando1 ; 2. O comando shift cuja sintaxe shift n , podendo o n assumir

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves qualquer valor numrico (porm seu default 1 como no exemplo dado), despreza os n primeiros parmetros, tornando o parmetro de ordem n+1 , o primeiro ou seja, o $1 .

Bem, agora que voc j sabe mais sobre passagem de parmetros do que eu, vamos voltar nossa cdteca para fazer o script de incluso de CDs no meu banco chamado musicas . O programa muito simples (como tudo em Shell) e vou list-lo para voc ver: Exemplos$ cat musinc #!/bin/bash # Cadastra CDs (versao 1) # echo $1 >> musicas

O script fcil e funcional, limito-me a anexar ao fim do arquivo musicas o parmetro recebido. Vamos cadastrar 3 lbuns para ver se funciona (para no ficar enchendo lingia, vou supor que em cada CD s existem 2 msicas):$ musinc album 3^Artista5~Musica5:Artista6~Musica5 $ musinc album 1^Artista1~Musica1:Artista2~Musica2 $ musinc album 2^Artista3~Musica3:Artista4~Musica4

Listando o contedo de musicas.$ cat musicas album 3^Artista5~Musica5:Artista6~Musica6 album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4

No est funcional como achava que deveria ficar podia ter ficado melhor. Os lbuns esto fora de ordem, dificultando a pesquisa. Vamos alterar nosso script e depois test-lo novamente:$ cat musinc #!/bin/bash # Cadastra CDs (versao 2) # echo $1 >> musicas sort musicas -o musicas

Vamos cadastrar mais um:$ musinc album 4^Artista7~Musica7:Artista8~Musica8

Agora vamos ver o que aconteceu com o arquivo musicas :$ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesalbum 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8

Simplesmente inseri uma linha que classifica o arquivo musicas dando a sada nele mesmo (para isso serve a opo -o ), aps cada lbum ser anexado. Oba! Agora est legal e quase funcional. Mas ateno, no se desespere! Esta no a verso final. O programa ficar muito melhor e mais amigvel, em uma nova verso que desenvolveremos aps aprendermos a adquirir os dados da tela e formatar a entrada. Exemplos Ficar listando com o comando cat no est com nada, vamos ento fazer um programa chamado muslist para listar um lbum cujo nome ser passado como parmetro:$ cat muslist #!/bin/bash # Consulta CDs (versao 1) # grep $1 musicas

Vamos execut-lo, procurando pelo album 2 . Como j vimos antes, para passar a cadeia album 2 necessrio proteg-la da interpretao do Shell, para que ele no a interprete como dois parmetros. Vamos fazer assim:$ muslist lbum 2 grep: cant open 2 musicas: album 1^Artista1~Musica1:Artista2~Musica2 musicas: album 2^Artista3~Musica3:Artista4~Musica4 musicas: album 3^Artista5~Musica5:Artista6~Musica6 musicas: album 4^Artista7~Musica7:Artista8~Musica8

Que lambana! Onde est o erro? Eu tive o cuidado de colocar o parmetro passado entre aspas, para o Shell no dividi-lo em dois! , mas repare como est o grep executado:grep $1 musicas

Mesmo colocando lbum 2 entre aspas, para que fosse encarado como um nico parmetro, quando o $1 foi passado pelo Shell para o comando grep , transformouse em dois argumentos. Desta forma o contedo final da linha, que o comandogrep

executou foi o seguinte:

grep album 2 musicas

Como a sintaxe do grep : =grep [arq1, arq2, ..., arqn]= o grep entendeu que deveria procurar a cadeia de caracteres album nos arquivos 2 e musicas , Por no existir o arquivo 2 gerou o erro, e por encontrar a palavra album em todos os registros de musicas , listou a todos.

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Sempre que a cadeia de caracteres a ser passada para o comando grep possuir brancos ou TAB , mesmo que dentro de variveis, coloque-a sempre entre aspas para evitar que as palavras aps o primeiro espao em branco ou TAB sejam interpretadas como nomes de arquivos. Por outro lado, melhor ignorarmos maisculas e minsculas na pesquisa. Resolveramos os dois problemas se o programa tivesse a seguinte forma:$ cat muslist #!/bin/bash # Consulta CDs (versao 2) # grep -i $1 musicas

Neste caso, usamos a opo -i do grep , que como j vimos, serve para ignorar maisculas e minsculas, e colocamos o $1 entre aspas, para que o grep continuasse a ver a cadeia de caracteres resultante da expanso da linha peloShell

como um nico argumento de pesquisa.

$ muslist album 2 album2^Artista3~Musica3:Artista4~Musica4

Agora repare que o grep localiza a cadeia pesquisada em qualquer lugar do registro, ento da forma que estamos fazendo, podemos pesquisar por lbum, por msica, por intrprete ou at por um pedao de qualquer um destes. Quando conhecermos os comandos condicionais, montaremos uma nova verso de muslist que permitir especificar por qual campo pesquisar. A voc vai me dizer: - Poxa, mas um saco ter que colocar o argumento de pesquisa entre aspas na hora de passar o nome do lbum. Esta forma no nem um pouco amigvel! - Tem razo, e por isso vou te mostrar uma outra forma de fazer o que voc pediu:$ cat muslist #!/bin/bash # Consulta CDs (versao 3) # grep -i $* musicas $ muslist album 2 album 2^Artista3~Musica3:Artista4~Musica4

Desta forma, o $* , que significa todos os parmetros, ser substitudo pela cadeiaalbum 2

(de acordo com o exemplo anterior, fazendo o que voc queria.

No se esquea o problema do Shell no se voc pode ou no fazer uma determinada coisa. O problema decidir qual a melhor forma de faz-la, j que para desempenhar qualquer tarefa, a quantidade de opes enorme.

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Ah! Em um dia de vero voc foi praia, esqueceu o CD no carro, aquele solzinho de 40 graus empenou o seu CD e agora voc precisa de uma ferramenta para remov-lo do banco de dados? No tem problema, vamos desenvolver um script chamado musexc , para excluir estes CDs. Antes de desenvolver o bacalho, quero te apresentar a uma opo bastante til da famlia de comandos grep . a opo -v , que quando usada lista todos os registros da entrada, exceto o(s) localizado(s) pelo comando. Vejamos: Exemplos$ grep -v album 2 musicas album 1^Artista1~Musica1:Artista2~Musica2 album 3^Artista5~Musica5:Artista6~Musica6 album 4^Artista7~Musica7:Artista8~Musica8

Conforme eu expliquei antes, o grep do exemplo listou todos os registros de musicas exceto o referente a album 2 , porque atendia ao argumento do comando. Estamos ento prontos para desenvolver o script para remover aquele CD empenado da sua CDteca. Ele tem a seguinte cara:$ cat musexc #!/bin/bash # Exclui CDs (versao 1) # grep -v $1 musicas > /tmp/mus$$ mv -f /tmp/mus$$ musicas

Na primeira linha mandei para /tmp/mus$$ o arquivo musicas, sem os registros que atendessem a consulta feita pelo comando grep . Em seguida, movi (que, no duro, equivale a renomear) /tmp/mus$$ por cima do antigo musicas . Usei o arquivo /tmp/mus$$ como arquivo de trabalho, porque como j havia citado no artigo anterior, o $$ contm o PID (Process Identification ou identificao do processo) e desta forma cada um que editar o arquivo musicas o far em um arquivo de trabalho diferente, desta forma evitando colises no uso. - A cara, estes programas que fizemos at aqui esto muito primrios em virtude da falta de ferramentas que ainda temos. Mas bom, enquanto eu tomo mais um chope, voc ir para casa praticar em cima dos exemplos dados porque, eu prometo, chegaremos a desenvolver um sistema bacana para controle dos seus CDs. - Quando nos encontrarmos da prxima vez, vou te ensinar como funcionam os comandos condicionais e aprimoraremos mais um pouco estes scripts. - Por hoje chega! J falei demais e preciso molhar a palavra porque estou de goela seca! - Garom! Mais um sem colarinho! Vou aproveitar tambm para mandar o meu jab: diga para os amigos que quem estiver afim de fazer um curso porreta de programao em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dvida ou falta de companhia para um chope ou at para falar mal dos polticos s mandar um e-mail para mim.

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Valeu!Publicado em Shell | Tagged $, bash, cat, chmod, egrep, fgrep, grep, ls, PID, regexp, Shell, shift, | | Deixar um comentrio

Papo de Botequim Parte 3maro 5, 2008 por jneves

Trabalhando com cadeias O Comando cut (que no a central de trabalhadores) O comando cut com a opo -c O comando cut com a opo -f Se tem cut tem paste Quem est em p, deita Usando separadores O Comando tr Trocando caracteres com tr Removendo caracteres com tr Xpremendo com tr Comandos Condicionais O Comando if - Garon, traga dois chopes por favor que hoje eu vou ter que falar muito.

Trabalhando com cadeiasPelo ttulo acima no pense voc que vou lhe ensinar a ser carcereiro! Estou me referindo a cadeia de caracteres!

O Comando cut (que no a central de trabalhadores)Primeiro quero te mostrar, de forma eminentemente prtica uma instruo simples de usar e muito til: o comando cut , Esta instruo usada para cortar um determinado pedao de um arquivo e tem duas formas distintas de uso

O comando cut com a opo -cCom esta opo, o comando tem a seguinte sintaxe:cut -c PosIni-PosFim [arquivo]

Onde:PosIni = Posio inicial PosFim = Posio final

$ cat numeros 1234567890 0987654321

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves1234554321 9876556789 $ cut -c1-5 numeros 12345 09876 12345 98765 $ cut -c-6 numeros 123456 098765 123455 987655 $ cut -c4- numeros 4567890 7654321 4554321 6556789 $ cut -c1,3,5,7,9 numeros 13579 08642 13542 97568 $ cut -c -3,5,8- numeros 1235890 0986321 1235321 9875789

Como d para ver, no duro mesmo existem quatro sintaxes distintas: na primeira(-c 1-5),

eu especifiquei uma faixa, na segunda (-c -6), especifiquei tudo at

uma posio, na terceira (-c 4-) de uma determinada posio em diante e na quarta (-c 1,3,5,7,9) , determinadas posies. A ltima (-c -3,5,8 foi s para -) mostrar que podemos misturar tudo.

O comando cut com a opo -fMas no pense voc que acabou por a! Como voc deve ter percebido esta forma de cut til para arquivos com campos de tamanho fixo, mas atualmente o que mais existe so arquivos com campos de tamanho variveis, onde cada campo termina com um delimitador. Vamos dar uma olhada no arquivo musicas que comeamos a preparar no nosso papo na ltima vez que viemos aqui no botequim.$ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8

Ento, recapitulando, o seu leiaute o seguinte:nome do album^interprete1~nome da musica1:...:interpreten~nome da musican

isto , o nome do lbum ser separado por um circunflexo ( ^ ) do resto do registro, que formado por diversos grupos compostos pelo intrprete de cada msica do

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves CD e a respectiva msica interpretada. Estes grupos so separados entre si por dois-pontos ( : ) e internamente, o nome do intrprete ser separado por um til ( ~ ) do nome da msica. Ento para pegarmos os dados referentes a todas as segundas msicas do arquivomusicas ,

devemos fazer:

$ cut -f2 -d: musicas Artista2~Musica2 Artista4~Musica4 Artista6~Musica5 Artista8~Musica8

Ou seja, cortamos o segundo campo ( -f de field em ingls) delimitado ( -d ) por dois-pontos ( : ). Mas, se quisermos somente os intrpretes, devemos fazer:$ cut -f2 -d: musicas | cut -f1 -d~ Artista2 Artista4 Artista6 Artista8

Para entender isso, vamos pegar a primeira linha de musicas :$ head -1 musicas album 1^Artista1~Musica1:Artista2~Musica2

Ento observe o que foi feito: Delimitador do primeiro cut ( : )album 1^Artista1~Musica1:Artista2~Musica2

Desta forma, no primeiro cut , o primeiro campo do delimitador ( -d ) dois-pontos ( : ) album 1^Artista1~Musica1 e o segundo, que o que nos interessa, Artista2~Musica2. Vamos ento ver o que aconteceu no segundo cut : Novo delimitador ( ~ )Artista2~Musica2

Agora, primeiro campo do delimitador ( -d ) til ( ~ ), que o que nos interessa, Artista2 e o segundo Musica2. Se o raciocnio que fizemos para a primeira linha for aplicado no restante do arquivo, chegaremos resposta anteriormente dada.

Se tem cut tem pasteComo j era de se esperar, o comando paste serve para colar, s que aqui no Shell o que ele cola so arquivos. S para comear a entend-lo, vamos fazer assim::paste arq1 arq2

Desta forma ele mandar para a sada padro ( stdout ) cada um dos registros de

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesarq1

ao lado dos registros de arq2 correspondentes e caso nenhum delimitador seja

especificado, ele usar por default o . O paste um comando pouco usado por sua sintaxe ser pouco conhecida. Vamos brincar com 2 arquivos criados da seguinte forma:$ seq 10 > inteiros $ seq 2 2 10 > pares

Para ver o contedo dos arquivos criados, vamos usar o paste na sua forma careta que mostramos acima:$ paste inteiros pares 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10

Quem est em p, deitaAgora vamos transformar a coluna do pares em linha:$ paste -s pares 2 4 6 8 10

Usando separadoresComo j foi dito, o separador default do paste o , mas isso pode ser alterado com a opo -d . Ento para calcular a soma do contedo de pares primeiramente faramos:$ paste -s -d+ pares # tambm poderia ser -sd+ 2+4+6+8+10

e depois passaramos esta linha para a calculadora ( bc ) e ento ficaria:$ paste -sd+ pares | bc 30

Assim sendo, para calcular o fatorial do nmero contido em $Num , basta:$ seq $Num | paste -sd* | bc

Com o comando paste voc tambm pode montar formataes exticas como esta a seguir:$ ls | paste -s -dttn

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesarq1 arq4 arq2 arq5 arq3 arq6

O que aconteceu foi o seguinte: foi especificado para o comando paste que ele transformaria linhas em colunas (pela opo -s ) e que os seus separadores (! Ele aceita mais de um, mas somente um aps cada coluna criada pelo comando) seriam uma , outra e um , gerando desta forma a sada tabulada em 3 colunas. Agora que voc j entendeu isto, veja como fazer a mesma coisa, porm de forma mais fcil e menos bizarra e tosca, usando o mesmo comando mas com a seguinte sintaxe:$ ls | paste - arq1 arq4 arq2 arq5 arq3 arq6

E isto acontece porque se ao invs de especificarmos os arquivos colocarmos o sinal de menos ( - ), o comando paste os substitui pela sada ou entrada padro conforme o caso. No exemplo anterior os dados foram mandados para a sada padro ( stdout ), porque o pipe ( | ) estava desviando a sada do ls para a entrada padro ( stdin ) do paste , mas veja o exemplo a seguir:$ cat arq1 predisposio privilegiado profissional $ cat arq2 encher mrio motor $ cut -c-3 arq1 | paste -d arq2 preencher primrio promotor

Neste caso, o cut devolveu as trs primeiras letras de cada registro de arq1 , opaste

foi montado para no ter separador ( -d"" ) e receber a entrada padro

(desviada pelo pipe) no trao ( - ) gerando a sada juntamente com arq2 .

O Comando trOutro comando muito interessante o tr que serve para substituir, comprimir ou remover caracteres. Sua sintaxe segue o seguinte padro:tr [opes] cadeia1 [cadeia2]

O comando tr copia o texto da entrada padro (stdin), troca as ocorrncia dos caracteres de cadeia1 pelo seu correspondente na cadeia2 ou troca mltiplas ocorrncias dos caracteres de cadeia1 por somente um caracter, ou ainda remove caracteres da cadeia1 . As principais opes do comando so:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Principais Opes do comando tr OpoSignificado -s -d Comprime n ocorrncias de cadeia1 em apenas uma Remove os caracteres de cadeia1

Trocando caracteres com trPrimeiro vou te dar um exemplo bem bobo:$ echo bobo | tr o a baba

Isto , troquei todas as ocorrncias da letra o pela letra a . Suponha que em um determinado ponto do meu script eu pea ao operador para teclar s ou n (sim ou no), e guardo sua resposta na varivel $Resp . Ora o contedo de $Resp pode estar com letra maiscula ou minscula, e desta forma eu teria que fazer diversos testes para saber se a resposta dada foi S , s , N ou n . Ento o melhor fazer:$ Resp=$(echo $Resp | tr SN sn)

e aps este comando eu teria certeza que o contedo de $Resp seria um s ou umn.

Se o meu arquivo ArqEnt est todo escrito com letras maisculas e desejo passlas para minsculas eu fao:$ tr A-Z a-z < ArqEnt > /tmp/$$ $ mv -f /tmp/$$ ArqEnt

Note que neste caso usei a notao A-Z para no escrever ABCD...YZ . Outro tipo de notao que pode ser usada so as escape sequences (prefiro escrever no bom e velho portugus, mas nesse caso como eu traduziria? Seqncias de escape? Meio sem sentido, n? Mas v l) que tambm so reconhecidas por outros comandos e tambm na linguagem C, e cujo significado voc ver a seguir: Escape Sequences Seqncia Significado t n v f r \ Tabulao Nova linha Tabulao Vertical Nova Pgina Uma barra invertida Octal 11 12 13 14 134

Incio da linha 15

Removendo caracteres com trEnto deixa eu te contar um causo: um aluno que estava danado comigo, resolveu complicar a minha vida e em um exerccio prtico valendo nota que passei para ser feito no computador, me entregou o script com todos os comandos separados por ponto-e-vrgula (lembra que eu disse que o ponto-e-vrgula servia para separar diversos comandos em uma mesma linha?).

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Vou dar um exemplo simplificado e idiota de uma tripa assim:$ cat confuso echo leia Programao Shell Linux do Julio Cezar Neves > livro;cat livro;pwd;ls;rm -f lixo 2>/dev/null;cd ~

Eu executava o programa e ele funcionava:$ confuso leia Programao Shell Linux do Julio Cezar Neves /home/jneves/LM confuso livro musexc musicas musinc muslist numeros

Mas nota de prova coisa sria (e nota de dlar mais ainda comando:$ tr ; n < confuso echo leia Programao Shell Linux do Julio Cezar Neves pwd ls rm -f lixo 2>/dev/null cd ~

) ento, para

entender o que o aluno havia feito, o chamei e em sua frente executei o seguinte

O cara ficou muito desapontado, porque em 2 ou 3 segundos eu desfiz a gozao que ele perdera horas para fazer. Mas preste ateno! Se eu estivesse em uma mquina com Unix, eu teria feito:$ tr ; 12 < confuso

Xpremendo com trAgora veja a diferena entre os dois comandos date : o que fiz hoje e outro que foi executado h duas semanas:$ date # Hoje 2004

Sun Sep 19 14:59:54 $ date Sun Sep

# H duas semanas 5 10:12:33 2004

Para pegar a hora eu deveria fazer:$ date | cut -f 4 -d 14:59:54

Mas duas semanas antes ocorreria o seguinte:$ date | cut -f 4 -d 5

Mas observe porque:$ date # H duas semanas

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio NevesSun Sep 5 10:12:33 2004

Como voc pode notar, existem 2 caracteres em branco antes do 5 (dia), o que estraga tudo porque o terceiro pedao est vazio e o quarto o dia ( 5 ). Ento o ideal seria comprimir os espaos em brancos sucessivos em somente um espao para poder tratar as duas cadeias resultantes do comando date da mesma forma, e isso se faz assim:$ date | tr -s a Sun Sep 5 10:12:33 2004

Como voc pode ver no existem mais os dois espaos, ento agora eu poderia cortar:$ date | tr -s | cut -f 4 -d 10:12:33

Olha s como o Shell j est quebrando o galho. Veja este arquivo que foi baixado de uma mquina com aquele sistema operacional que pega vrus:$ cat -ve ArqDoDOS.txt Este arquivo^M$ foi gerado pelo^M$ DOS/Rwin e foi^M$ baixado por um^M$ ftp mal feito.^M$

E agora eu quero te dar duas dicas: Dica #1 A opo -v do cat mostra os caracteres de controle invisveis, com a notao ^L , onde ^ a tecla control e L a respectiva letra. A opo -e mostra o final da linha como um cifro ( $ ).

Dica #2 Isto ocorre porque no formato DOS (ou rwin), o fim dos registros formado por um carriage-return ( r ) e um line-feed ( n ). No Linux porm o final do registro tem somente o line-feed.

Vamos ento limpar este arquivo.$ tr -d r < ArqDoDOS.txt > /tmp/$$ $ mv -f /tmp/$$ ArqDoDOS.txt

Agora vamos ver o que aconteceu:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves$ cat -ve ArqDoDOS.txt Este arquivo$ foi gerado pelo$ DOS/Rwin e foi$ baixado por um$ ftp mal feito.$

Bem a opo -d do tr remove o caractere especificado de todo o arquivo. Desta forma eu removi os caracteres indesejados salvando em um arquivo de trabalho e posteriormente renomeei-o para a sua designao original. Obs: No Unix eu deveria fazer:$ tr -d 15 < ArqDoDOS.txt > /tmp/$$

Isto aconteceu porque o ftp foi feito do modo binrio (ouimage ),

isto , sem a interpretao do texto. Se antes da

transmisso do arquivo tivesse sido estipulada a opo ascii do ftp , isto no teria ocorrido.

- Olha, depois desta dica t comeando a gostar deste tal de Shell, mas ainda tem muita coisa que no consigo fazer. - Pois , ainda no te falei quase nada sobre programao em Shell, ainda tem muita coisa para aprender, mas com o que aprendeu, j d para resolver muitos problemas, desde que voc adquira o modo Shell de pensar. Voc seria capaz de fazer um script para me dizer quais so as pessoas que esto logadas h mais de um dia no seu servidor? - Claro que no! Para isso seria necessrio eu conhecer os comandos condicionais que voc ainda no me explicou como funcionam. - Deixa eu tentar mudar um pouco a sua lgica e traz-la para o modo Shell de pensar, mas antes melhor tomarmos um chope Chico, traz mais dois - Agora que j molhei a palavra, vamos resolver o problema que te propus. Repare como funciona o comando who:$ who jneves rtorres pts/1 pts/0 Sep 18 13:40 Sep 20 07:01 Sep 20 08:19 Sep 20 10:01

rlegaria pts/1 lcarlos pts/3

E veja tambm o date :$ date Mon Sep 20 10:47:19 BRT 2004

Repare que o ms e o dia esto no mesmo formato em ambos os comandos. Algumas vezes um comando tem a sada em http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

portugus e o outro em ingls. Quando isso ocorrer, voc pode usar o seguinte artifcio:$ date Mon Sep 20 10:47:19 BRT 2004 $ LANG=pt_BR date Seg Set 20 10:47:19 BRT 2004

Desta forma passando a sada do comando date para portugus.

Ora, se em algum registro do who eu no encontrar a data de hoje, sinal que o cara est logado h mais de um dia, j que ele no pode ter se logado amanh Ento vamos guardar o pedao que importa da data de hoje para procur-la na sada do who :$ Data=$(date | cut -c 5-10)

Eu usei a construo $(...) , para priorizar a execuo dos comandos antes de atribuir a sua sada varivel $Data . Vamos ver se funcionou:$ echo $Data Sep 20

Beleza! Agora, o que temos que fazer procurar no comando who os registros que no possuem esta data. - Ah! Eu acho que estou entendendo! Voc falou em procurar e me ocorreu o comando grep , estou certo? - Certssimo! S que eu tenho que usar o grep com aquela opo que ele s lista os registros nos quais ele no encontrou a cadeia. Voc se lembra que opo essa? - Claro, a opo -v - Isso! T ficando bo! Ento vamos ver:$ who | grep -v $Data jneves pts/1 Sep 18 13:40

- E se eu quisesse mais um pouco de perfumaria eu faria assim:$ who | grep -v $Data | cut -f1 -d jneves

- Viu? No foi necessrio usar nenhum comando condicional, at porque o nosso mais usado comando condicional, o famoso if , no testa condio, mas sim instrues, como veremos agora.

Comandos CondicionaisVeja as linhas de comando a seguir:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

$ ls musicas musicas $ echo $? 0 $ ls ArqInexistente ls: ArqInexistente: No such file or directory $ echo $? 1 $ who | grep jneves jneves pts/1 Sep 18 13:40 (10.2.4.144)

$ echo $? 0 $ who | grep juliana $ echo $? 1

- O que esse $? faz a? Comeando por cifro ( $ ) parece ser uma varivel, certo? - Sim uma varivel que contm o cdigo de retorno da ltima instruo executada. Posso te garantir que se esta instruo foi bem sucedida, $? ter o valor zero, caso contrrio seu valor ser diferente de zero.

O Comando ifO que o nosso comando condicional if faz testar a varivel $? . Ento vamos ver a sua sintaxe:if cmd then cmd1 cmd2 cmdn else cmd3 cmd4 cmdm fi

ou seja: caso comando cmd tenha sido executado com sucesso, os comandos do bloco do then ( cmd1 , cmd2 e cmdn ) sero executados, caso contrrio, os comandos executados sero os do bloco opcional do else ( cmd3 , cmd4 e cmdm ), terminando com um fi . Vamos ver na prtica como isso funciona usando um scriptizinho que serve para incluir usurios no /etc/passwd :$ cat incusu #!/bin/bash # Verso 1 if then echo Usuario $1 j existe else grep ^$1 /etc/passwd

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevesif then echo Usurio $1 includo em /etc/passwd else echo Problemas no cadastramento. Voc root? fi fi useradd $1

Repare que o if est testando direto o comando grep e esta a sua finalidade. Caso o if seja bem sucedido, ou seja, o usurio (cujo nome est em $1 ) foi encontrado em /etc/passwd , os comandos do bloco do then sero executados (neste exemplo somente o echo ) e caso contrrio, as instrues do bloco do else que sero executadas, quando um novo if testa se o comando useradd foi executado a contento, criando o registro do usurio em /etc/passwd , ou no quando dar a mensagem de erro. Vejamos sua execuo, primeiramente passando um usurio j cadastrado:$ incusu jneves jneves:x:54002:1001:Julio Neves:/home/jneves:/bin/bash Usuario jneves ja existe

Como j vimos diversas vezes, mas sempre bom insistir no tema para que voc j fique precavido, no exemplo dado surgiu uma linha indesejada, ela a sada do comando grep . Para evitar que isso acontea, devemos desviar a sada desta instruo para /dev/null , ficando assim:$ cat incusu #!/bin/bash # Verso 2 if then echo Usuario $1 j existe else if then echo Usurio $1 includo em /etc/passwd else echo Problemas no cadastramento. Voc root? fi fi useradd $1 grep ^$1 /etc/passwd > /dev/null # ou: if grep -q ^$1 /etc/passwd

Agora vamos test-lo como usurio normal (no root):$ incusu ZeNinguem ./incusu[6]: useradd: not found

Problemas no cadastramento. Voc root?

Epa, aquele erro no era para acontecer! Para evitar que isso acontea devemos mandar tambm a sada de erro (strerr, lembra?) do useradd para /dev/null , ficando na verso final assim:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves$ cat incusu #!/bin/bash # Verso 3 if then echo Usuario $1 j existe else if then echo Usurio $1 includo em /etc/passwd else echo Problemas no cadastramento. Voc root? fi fi useradd $1 2> /dev/null grep ^$1 /etc/passwd > /dev/null

Depois destas alteraes e de fazer um su (me tornar root) vejamos o seu comportamento:$ incusu botelho Usurio botelho incluido em /etc/passwd

E novamente:$ incusu botelho Usurio botelho j existe

Lembra que eu falei que ao longo dos nossos papos e chopes os nossos programas iriam se aprimorando? Ento vejamos agora como poderamos melhorar o nosso programa para incluir msicas:$ cat musinc #!/bin/bash # Cadastra CDs (versao 3) # if then echo Este lbum j est cadastrado else echo $1 >> musicas sort musicas -o musicas fi grep ^$1$ musicas > /dev/null

Como voc viu, uma pequena evoluo da verso anterior, assim, antes de incluir um registro (que pela verso anterior poderia ser duplicado), testamos se o registro comeava ( ^ ) e terminava ( $ ) igual ao parmetro passado ( $1 ). O uso do circunflexo ( ^ ) no incio da cadeia e cifro ( $ ) no fim, so para testar se o parmetro passado (o lbum e seus dados) so exatamente iguais a algum registro anteriormente cadastrado e no somente igual a um pedao de algum dos registros. Vamos execut-lo passando um lbum j cadastrado:$ musinc album 4^Artista7~Musica7:Artista8~Musica8 Este lbum j est cadastrado

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

E agora um no cadastrado:$ musinc album 5^Artista9~Musica9:Artista10~Musica10 $ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8 album 5^Artista9~Musica9:Artista10~Musica10

- Como voc viu, o programa melhorou um pouquinho, mas ainda no est pronto. medida que eu for te ensinando a programar em shell, nossa CDteca ir ficando cada vez melhor. - Entendi tudo que voc me explicou, mas ainda no sei como fazer um if para testar condies, ou seja o uso normal do comando. - Cara, para isso existe o comando test , ele que testa condies. O comando if testa o comando test . Mas isso est meio confuso e como j falei muito, estou precisando de uns chopes para molhar a palavra. Vamos parando por aqui e na prxima vez te explico direitinho o uso do test e de diversas outras sintaxes do if . - Falou! Acho bom mesmo porque eu tambm j t ficando zonzo e assim tenho tempo para praticar esse monte de coisas que voc me falou hoje. - Para fixar o que voc aprendeu, tente fazer um scriptizinho para informar se um determinado usurio, que ser passado como parmetro esta logado (arghh!) ou no. - A Chico, mais dois chopes por favor Vou aproveitar tambm para mandar o meu jab: diga para os amigos que quem estiver afim de fazer um curso porreta de programao em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dvida ou falta de companhia para um chope ou at para falar mal dos polticos s mandar um e-mail para mim. Valeu!Publicado em Shell | Tagged $, bash, cat, cut, date, echo, grep, head, if, mv, paste, seq, Shell, sort, tr | Deixar um comentrio

Papo de Botequim Parte 4maro 5, 2008 por jneves

O Comando test Querida, Encolheram o Comando Condicional E tome de test Acaso Casa com case - E a cara, tentou fazer o exerccio que te pedi para revigorar as idias? - Claro, que sim! Em programao, se voc no treinar, no aprende. Voc me http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves pediu para fazer um scriptizinho para informar se um determinado usurio, que ser passado como parmetro esta logado (arghh!) ou no. Eu fiz o seguinte:$ cat logado #!/bin/bash # Pesquisa se uma pessoa est logada ou no if who | grep $1 then echo $1 est logado else echo $1 no se encontra no pedao fi

- Calma rapaz! J vi que voc chegou cheio de teso, primeiro vamos pedir os nossos chopes de praxe e depois vamos ao Shell. Chico traz dois chopes, um sem colarinho! - Agora que j molhamos os nossos bicos, vamos dar uma olhadinha na execuo do seu bacalho:$ logado jneves jneves pts/0 Oct 18 12:02 (10.2.4.144)

jneves est logado

Realmente funcionou. Passei o meu login como parmetro e ele disse que eu estava logado, porm ele mandou uma linha que eu no pedi. Esta linha a sada do comando who , e para evitar que isso acontea s mand-la para o buraco negro que a esta altura voc j sabe que o /dev/null . Vejamos ento como ficaria:$ cat logado #!/bin/bash # Pesquisa se uma pessoa est logada ou no (verso 2) if who | grep $1 > /dev/null then echo $1 est logado else echo $1 no se encontra no pedao fi

Agora vamos aos testes:$ logado jneves jneves est logado $ logado chico chico no se encontra no pedao

Ah, agora sim! Lembre-se desta pegadinha, a maior parte dos comandos tem uma sada padro e uma sada de erros (o grep uma das poucos excees, j que no d mensagem de erro quando no acha uma cadeia) e necessrio estarmos atentos para redirecion-las para o

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

buraco negro quando necessrio. Bem, agora vamos mudar de assunto: na ltima vez que nos encontramos aqui no Botequim, eu estava te mostrando os comandos condicionais e, quando j estvamos de goela seca falando sobre o if, voc me perguntou como se testa condies. Vejamos ento o

O Comando testBem, todos estamos acostumados a usar o if testando condies, e estas so sempre, maior, menor, maior ou igual, menor ou igual, igual e diferente. Bem, em Shell para testar condies, usamos o comando test , s que ele muito mais poderoso que o que estamos habituados. Primeiramente vou te mostrar as principais opes (existem muitas outras) para testarmos arquivos em disco: Opes do Comando test para arquivos OpoVerdadeiro se:-e arq arq -s arq arq -f arq arq -d arq arq -r arq arq -w arq arq -x arq arq

existe existe e tem tamanho maior que zero existe e um arquivo regular existe e um diretrio; existe e com direito de leitura existe e com direito de escrita existe e com direito de execuo

Veja agora as principais opes para teste de cadeias de caracteres: Opes do comando test para cadeias de caracteres Opo Verdadeiro se:-z cadeia -n cadeia cadeia c1 = c2

Tamanho de cadeia zero Tamanho de cadeia maior que zero A cadeia cadeia tem tamanho maior que zero Cadeia c1 e c2 so idnticas

E pensa que acabou? Engano seu! Agora que vem o que voc est mais acostumado, ou seja as famosas comparaes com numricos. Veja a tabela: Opes do comando test para nmeros Opo Verdadeiro se:n1 -eq n2 n1 n1 -ne n2 n1 n1 -gt n2 n1 n1 -ge n2 n1 n1 -lt n2 n1 n1 -le n2 n1

Significado equal not equal greater than less than

e n2 so iguais e n2 no so iguais maior que n2 menor que n2

maior ou igual a n2 greater or equal menor ou igual a n2 less or equal

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Alm de tudo, some-se a estas opes as seguintes facilidades: Operadores Operador Parnteses ( ) Exclamao !-a -o

Finalidade Agrupar NegarE OU

lgico lgico

Ufa! Como voc viu tem coisa pr chuchu, e como eu te disse no incio, o nosso if muito mais poderoso que o dos outros. Vamos ver em uns exemplos como isso tudo funciona, primeiramente testaremos a existncia de um diretrio: Exemplos:if then cd lmb else mkdir lmb cd lmb fi test -d lmb

No exemplo, testei se existia um diretrio lmb definido, caso negativo ( else ), ele seria criado. J sei, voc vai criticar a minha lgica dizendo que o script no est otimizado. Eu sei, mas queria que voc o entendesse assim, para ento poder usar o ponto-de-espantao ( ! ) como um negador do test . Veja s:if then mkdir lmb fi cd lmb test ! -d lmb

Desta forma o diretrio lmb seria criado somente se ele ainda no existisse, e esta negativa deve-se ao ponto-de-exclamao ( ! ) precedendo a opo -d . Ao fim da execuo deste fragmento de script, o programa estaria com certeza dentro do diretrio lmb . Vamos ver dois exemplos para entender a diferena comparao entre nmeros e entre cadeias.cad1=1 cad2=01 if then echo As variveis so iguais. else echo As variveis so diferentes. fi test $cad1 = $cad2

Executando o fragmento de programa acima vem:As variveis so diferentes.

Vamos agora alter-lo um pouco para que a comparao seja numrica:

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Nevescad1=1 cad2=01 if then echo As variveis so iguais. else echo As variveis so diferentes. fi test $cad1 -eq $cad2

E vamos execut-lo novamente:As variveis so iguais.

Como voc viu nas duas execues obtive resultados diferentes porque a cadeia 01 realmente diferente da cadeia 1 , porm, a coisa muda quando as variveis so testadas numericamente, j que o nmero 1 igual ao nmero 01 . Exemplos: Para mostrar o uso dos conectores -o ( OU ) e -a ( E ), veja um exemplo animal feito direto no prompt (me desculpem os zologos, mas eu no entendendo nada de reino, filo, classe, ordem, famlia, gnero e espcie, desta forma o que estou chamando de famlia ou de gnero tem grande chance de estar incorreto):$ Familia=felinae $ Genero=gato $ if test $Familia = canidea -a $Genero = lobo -o $Familia = felina -a $Genero = leo > then > > else > > fi Pode passar a mo echo Pode passar a mo echo Cuidado

Neste exemplo caso o animal fosse da famlia candea E ( -a ) do gnero lobo, OU ( o)

da familia felina E ( -a ) do gnero leo, seria dado um alerta, caso contrrio a

mensagem seria de incentivo. Os sinais de maior ( > ) no incio das linhas internas ao if so os prompts de continuao (que esto definidos na varivel $PS2 ) e quando o Shell identifica que um comando continuar na linha seguinte, automaticamente ele o coloca at que o comando seja encerrado. Vamos mudar o exemplo para ver se continua funcionando:$ Familia=felino $ Genero=gato $ if test $Familia = felino -o $Familia = canideo -a $Genero = ona -o $Genero = lobo > then

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves> > else > > fi Cuidado echo Pode passar a mo echo Cuidado

Obviamente a operao redundou em erro, isto foi porque a opo -a tem precedncia sobre a -o , e desta forma o que primeiro foi avaliado foi a expresso:$Familia = canideo -a $Genero = ona

Que foi avaliada como falsa, retornando o seguinte:$Familia = felino -o FALSO -o $Genero = lobo

Que resolvida vem:VERDADEIRO -o FALSO -o FALSO

Como agora todos conectores so -o , e para que uma srie de expresses conectadas entre si por diversos OU lgicos seja verdadeira, basta que uma delas seja, a expresso final resultou como VERDADEIRO e o then foi executado de forma errada. Para que isso volte a funcionar faamos o seguinte:$ if test ($Familia = felino -o $Familia = canideo) -a ($Genero = ona -o $Genero = lobo) > then > > else > > fi Pode passar a mo echo Pode passar a mo echo Cuidado

Desta forma, com o uso dos parnteses agrupamos as expresses com o conector-o ,

priorizando as suas execues e resultando:

VERDADEIRO -a FALSO

Para que seja VERDADEIRO o resultado duas expresses ligadas pelo conector -a necessrio que ambas sejam verdadeiras, o que no o caso do exemplo acima. Assim o resultado final foi FALSO sendo ento o else corretamente executado. Se quisermos escolher um CD que tenha faixas de 2 artistas diferentes, nos sentimos tentados a usar um if com o conector -a , mas sempre bom lembrarmos que o bash nos d muito recursos, e isso poderia ser feito de forma muito mais simples com um nico comando grep , da seguinte maneira:$ grep Artista1 musicas | grep Artista2

Da mesma forma para escolhermos CDs que tenham a participao do Artista1 e do Artista2 , no necessrio montarmos um if com o conector -o . O egrep (ougrep -E ,

sendo este mais aconselhvel) tambm resolve isso para ns. Veja como:

$ egrep (Artista1|Artista2) musicas

Ou (nesse caso especfico) o prprio grep puro e simples poderia nos quebrar o

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves galho:$ grep Artista[12] musicas

No egrep acima, foi usada uma expresso regular, onde a barra vertical ( | ) trabalha como um OU lgico e os parnteses so usados para limitar a amplitude deste OU . J no grep da linha seguinte, a palavra Artista deve ser seguida por um dos valores da lista formada pelos colchetes ( [ ] ), isto , 1 ou 2 . - T legal, eu aceito o argumento, o if do Shell muito mais poderoso que os outros caretas, mas c pra ns, essa construo de if test ... muito esquisita, pouco legvel. - voc tem razo, eu tambm no gosto disso e acho que ningum gosta. Acho que foi por isso, que o Shell incorporou outra sintaxe que substitui o comandotest .

Exemplos: Para isso vamos pegar aquele exemplo para fazer uma troca de diretrios, que era assim:if then mkdir lmb fi cd lmb test ! -d lmb

e utilizando a nova sintaxe, vamos faz-lo assim:if then mkdir lmb fi cd lmb [ ! -d lmb ]

Ou seja, o comando test pode ser substitudo por um par de colchetes ( [ ] ), separados por espaos em branco dos argumentos, o que aumentar enormemente a legibilidade, pois o comando if ir ficar com a sintaxe semelhante das outras linguagens e por isso este ser o modo que o comando test ser usado daqui para a frente.

Querida, Encolheram o Comando CondicionalSe voc pensa que acabou, est muito enganado. Repare a tabela (tabela verdade) a seguir: Valores Booleanos VERDADEIRO-FALSO FALSO-VERDADEIRO FALSO-FALSO E FALSO FALSO FALSO OU VERDADEIRO VERDADEIRO FALSO

VERDADEIRO-VERDADEIRO VERDADEIRO VERDADEIRO

Ou seja, quando o conector E e a primeira condio verdadeira, o resultado final pode ser VERDADEIRO ou FALSO , dependendo da segunda condio, j no conector OU , caso a primeira condio seja verdadeira, o resultado sempre ser

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio NevesVERDADEIRO

e se a primeira for falsa, o resultado depender da segunda condio.

Ora, os caras que desenvolveram o interpretador no so bobos e esto sempre tentando otimizar ao mximo os algoritmos. Portanto, no caso do conector E , a segunda condio no ser avaliada, caso a primeira seja falsa, j que o resultado ser sempre FALSO . J com o OU , a segunda ser executada somente caso a primeira seja falsa. Aproveitando disso, criaram uma forma abreviada de fazer testes. Batizaram o conector E de && e o OU de || e para ver como isso funciona, vamos us-los como teste no nosso velho exemplo de trocarmos de diretrio, que em sua ltima verso estava assim:if then mkdir lmb fi cd lmb [ ! -d lmb ]

Isso tambm poderia ser escrito da seguinte maneira:[ ! -d lmb ] && mkdir lmb cd lmb

Ou ainda retirando a negao ( ! ):[ -d lmb ] || mkdir lmb cd lmb

No primeiro caso, se o primeiro comando (o test que est representado pelos colchetes) for bem sucedido, isto , no existir o diretrio lmb , o mkdir ser efetuado porque a primeira condio era verdadeira e o conector era E . No exemplo seguinte, testamos se o diretrio lmb existia (no anterior testamos se ele no existia) e caso isso fosse verdade, o mkdir no seria executado porque o conector era OU . Outra forma:cd lmb || mkdir lmb

Neste caso, se o cd fosse mal sucedido, seria criado o diretrio lmb mas no seria feito o cd para dentro dele. Para executarmos mais de um comando desta forma, necessrio fazermos um grupamento de comandos, e isso se consegue com o uso de chaves ( { } ). Veja como seria o correto:cd lmb || { mkdir lmb cd lmb }

Ainda no est legal, porque caso o diretrio no exista, o cd dar a mensagem de erro correspondente. Ento devemos fazer:cd lmb 2> /dev/null || { mkdir lmb cd lmb }

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

Como voc viu o comando if nos permitiu fazer um cd seguro de diversas maneiras. sempre bom lembrarmos que o seguro a que me referi no tocante ao fato de que ao final da execuo voc sempre estar dentro de lmb , desde que voc tenha permisso entrar em lmb , permisso para criar um diretrio em ../lmb , haja espao em disco,

E tome de testUfa! Voc pensa que acabou? Ledo engano! Ainda tem uma forma de test a mais. Essa legal porque ela te permite usar padres para comparao. Estes padres atendem s normas de Gerao de Nome de Arquivos (File Name Generation, que so ligeiramente parecidas com as Expresses Regulares, mas no podem ser confundidas com estas). A diferena de sintaxe deste para o test que acabamos de ver que esse trabalha com dois pares de colchete da seguinte forma:[[ expresso ]]

Onde expresso uma das que constam na tabela a seguir: Expresses Condicionais Para Padres Expressocadeia == padro cadeia1 = padrao cadeia1 != padrao Verdadeiro cadeia1 < cadeia1 Verdadeiro cadeia1 > cadeia1 Verdadeiro expr1 && expr2 expr1 expr2

Retorna Verdadeiro se cadeia1 casa com padro se cadeia1 no casa com padrao . se cadeia1 vem antes de cadeia1 alfabeticamente. se cadeia1 vem depois de cadeia1 alfabeticamente

E lgico, verdadeiro se ambos expr1 e expr2 so verdadeiros OU lgico, verdadeiro se expr1 ou expr2 for verdadeiro

$ echo $H 13 $ [[ $H == [0-9] || $H == 1[0-2] ]] || echo Hora invlida Hora invlida $H=12 $ [[ $H == [0-9] || $H == 1[0-2] ]] || echo Hora invlida $

Neste exemplo, testamos se o contedo da varivel $H estava compreendido entre zero e nove ([0-9]) ou (||) se estava entre dez e doze (1[0-2]) , dando uma mensagem de erro caso no fosse. Exemplos: Para saber se uma varivel tem o tamanho de um e somente um caractere, faa:$ var=a $ [[ $var == ? ]] && echo var tem um caractere var tem um caractere $ var=aa $ [[ $var == ? ]] && echo var tem um caractere $

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Como voc pode imaginar, este uso de padres para comparao, aumenta muito o poderio do comando test . No incio deste papo, antes do ltimo chope, afirmamos que o comando if do interpretador Shell mais poderoso que o seu similar em outras linguagens. Agora que conhecemos todo o seu espectro de funes, diga-me: voc concorda ou no com esta assertiva?

Acaso Casa com caseVejamos um exemplo didtico: dependendo do valor da varivel $opc o script dever executar uma uma das opes: incluso, excluso, alterao ou fim. Veja como ficaria este fragmento de script:if then inclusao elif [ $opc -eq 2 ] then exclusao elif [ $opc -eq 3 ] then alteracao elif [ $opc -eq 4 ] then exit else echo Digite uma opo entre 1 e 4 fi [ $opc -eq 1 ]

Neste exemplo voc viu o uso do elif com um else if , esta a sintaxe vlida e aceita, mas poderamos fazer melhor, e isto seria com o comando case , que tem a sintaxe a seguir:case $var in padrao1) cmd1 cmd2 cmdn ;; padrao2) cmd1 cmd2 cmdn ;; padraon) cmd1 cmd2 cmdn ;; esac

Onde a varivel $var comparada aos padres padrao1, ..., padraon e caso um deles atenda, o bloco de comandos cmd1, ..., cmdn correspondente executado at encontrar um duplo ponto-e-vrgula ( ;; ), quando o fluxo do programa se desviar para instruo imediatamente aps o esac . Na formao dos padres, so aceitos os seguintes caracteres: Caracteres Para Formao de Padres Caractere Significado*

Qualquer caractere ocorrendo zero ou mais vezes

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves? [...]

Qualquer caractere ocorrendo uma vez Lista de caracteresOU

lgico

Para mostrar como fica melhor, vamos repetir o exemplo anterior, s que desta vez usaremos o case e no o if ... elif ... else ... fi .case $opc in 1) inclusao ;; 2) exclusao ;; 3) alteracao ;; 4) exit ;; *) echo Digite uma opo entre 1 e 4 esac

Como voc deve ter percebido, eu usei o asterisco como a ltima opo, isto , se o asterisco atende a qualquer coisa, ento ele servir para qualquer coisa que no esteja no intervalo de 1 a 4. Outra coisa a ser notada que o duplo ponto-evrgula no necessrio antes do esac . Exemplos: Vamos agora fazer um script mais radical. Ele te dar bom dia, boa tarde ou boa noite dependendo da hora que for executado, mas primeiramente veja estes comandos:$ date Tue Nov 9 19:37:30 BRST 2004

$ date +%H 19

O comando date informa a data completa do sistema, mas ele tem diversas opes para seu mascaramento. Neste comando, a formatao comea com um sinal de mais ( + ) e os caracteres de formatao vm aps um sinal de percentagem ( % ), assim o %H significa a hora do sistema. Dito isso vamos ao exemplo:$ cat boasvindas.sh #!/bin/bash # # # Programa bem educado que d bom-dia, boa-tarde ou boa-noite conforme a hora

Hora=$(date +%H) case $Hora in 0? | 1[01]) echo Bom Dia ;; 1[2-7] ;; * ;; esac exit ) echo Boa Noite ) echo Boa Tarde

Peguei pesado, n? Que nada vamos esmiuar a resoluo caso-a-caso (ou seria

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves

case-a-case?0? | 1[01]

)

Significa zero seguido de qualquer coisa ( ? ), ou ( | ) um seguido de

zero ou um ( [01] ) ou seja, esta linha pegou 01, 02, 09, 10 e 11;1[2-7]

Significa um seguido da lista de dois a sete, ou seja, esta linha pegou 12,

13, 17;*

Significa tudo que no casou com nenhum dos padres anteriores.

- Cara, at agora eu falei muito e bebi pouco. Agora eu vou te passar um exerccio para voc fazer em casa e me dar a resposta da prxima vez que nos encontrarmos aqui no botequim, t legal? - T, mas antes informe ao pessoal que est acompanhando este curso conosco como eles podem te encontrar para fazer crticas, contar piada, convidar para o chope, curso ou palestra ou at mesmo para falar mal dos polticos. - fcil, meu e-mail [email protected], mas pare de me embromar que eu no vou esquecer de te passar o script para fazer. o seguinte: quero que voc faa um programa que receber como parmetro o nome de um arquivo e que quando executado salvar este arquivo com o nome original seguido de um til ( ~ ) e colocar este arquivo dentro do vi (o melhor editor que se tem notcia) para ser editado. Isso para ter sempre a ltima cpia boa deste arquivo caso o cara faa alteraes indevidas. Obviamente, voc far as crticas necessrias, como verificar se foi passado um parmetro, se o arquivo passado existe, Enfim, o que te der na telha e voc achar que deve constar do script. Deu pr entender? - Hum, hum - Chico! Traz mais um sem colarinho que o cara aqui j est dando para entender!

Vou aproveitar tambm para mandar o meu jab: diga para os amigos que quem estiver afim de fazer um curso porreta de programao em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dvida ou falta de companhia para um chope ou at para falar mal dos polticos s mandar um e-mail para mim. Valeu!Publicado em Shell | Tagged bash, case, cd, do, done, else, esac, fi, if, mkdir, Shell, test, then, {, |, ||, } | Deixar um comentrio

Papo de Botequim Parte 5maro 5, 2008 por jneves

Comandos de Loop (ou lao) O comando for Primeira sintaxe do comando for Segunda sintaxe do comando for

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves Terceira sintaxe do comando for - Fala cara! E as idias esto em ordem? J fundiu a cuca ou voc ainda aguenta mais Shell? - Guento! T gostando muito! Gostei tanto que at caprichei no exerccio que voc passou. Lembra que voc me pediu para fazer um programa que receberia como parmetro o nome de um arquivo e que quando executado salvaria este arquivo com o nome original seguido de um til ( ~ ) e colocaria este arquivo dentro do vi ? - Claro que lembro, me mostre e explique como voc fez.$ cat vira #!/bin/bash # # # vira vi resguardando arquivo anterior == = =

# Verificando se foi passado 1 parametro if then echo Erro -> Uso: $0 exit 1 fi [ "$#" -ne 1 ]

Arq=$1 # Caso o arquivo no exista, nao ha copia para ser salva if then vi $Arq exit 0 fi [ ! -f "$Arq" ]

# Se nao puder alterar o arquivo vou usar o vi para que? if then echo Voce nao tem direito de gravacao em $Arq exit 2 fi [ ! -w "$Arq" ]

# Ja que esta tudo OK, vou salvar a copia e chamar o vi cp -f $Arq $Arq~ vi $Arq exit 0

- , beleza! Mas me diz uma coisa: porque voc terminou o programa com umexit 0 ?

- Ahhh! Eu descobri que o nmero aps o exit resultar no cdigo de retorno do programa (o $? , lembra?), e desta forma, como foi tudo bem sucedido, ele encerraria com o $? = 0 . Porm se voc observar, ver que caso o programa no tenha recebido o nome do arquivo ou caso o operador no tivesse direito de gravao sobre este arquivo, o cdigo de retorno ( $? ) seria diferente do zero. - Grande garoto, aprendeu legal, mas bom deixar claro que exit 0 ,

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves simplesmente exit ou no colocar exit , produzem igualmente um cdigo de retorno ( $? ) igual a zero. Agora vamos falar sobre as instrues de loop ou lao, mas antes vou passar o conceito de bloco de programa. At agora j vimos alguns blocos de programa. Quando te mostrei um exemplo para fazer um cd para dentro de um diretrio que era assim:cd lmb 2> /dev/null || { mkdir lmb cd lmb }

O fragmento contido entre as duas chaves ( {} ), forma um bloco de comandos. Tambm neste exerccio que acabamos de ver, em que salvamos o arquivo antes de edit-lo, existem vrios blocos de comandos compreendidos entre os then e osfi

do if .

Um bloco de comandos tambm pode estar dentro de um case , ou entre um do e um done . - Pera Julio, que do e done esse, no me lembro de voc ter falado nisso e olha estou prestando muita ateno - Pois , ainda no havia falado porque no havia chegado o momento propcio. Todas as instrues de loop ou lao, executam os comandos do bloco compreendido entre o do e o done .

Comandos de Loop (ou lao)As instrues de loop ou lao so o for , o while e o until que passarei a te explicar uma-a-uma a partir de agora.

O comando forSe voc est habituado a programar, certamente j conhece o comando for , mas o que voc no sabe que o for , que uma instruo intrinseca do Shell (isto significa que o cdigo fonte do comando faz parte do cdigo fonte do Shell, ou seja em bom programs um built-in), muito mais poderoso que os seus correlatos das outras linguagens. Vamos entender a sua sintaxe, primeiramente em portugus e depois como funciona no duro.para var em val1 val2 ... valn faa cmd1 cmd2 cmdn feito

Onde a varivel var assume cada um dos valores da lista val1 val2 ... valn e para cada um desses valores executa o bloco de comandos formado por cmd1 , cmd2 e cmdn Agora que j vimos o significado da instruo em portugus, vejamos a sintaxe

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves correta:

Primeira sintaxe do comando forfor var in val1 val2 ... valn do cmd1 cmd2 cmdn done

Vamos direto para os exemplos, para entender direito o funcionamento deste comando. Vamos escrever um script para listar todos os arquivos do nosso diretrio separados por dois-pontos, mas primeiro veja:$ echo * ArqDoDOS.txt1 confuso incusu logado musexc musicas musinc muslist

Isto , o Shell viu o asterisco ( * ) expandindo-o com o nome de todos os arquivos do diretrio e o comando echo jogou-os para a tela separados por espaos em branco. Visto isso vamos ver como resolver o problema a que nos propuzemos:$ cat testefor1 #!/bin/bash # 1o. Prog didtico para entender o for

for Arq in * do echo -n $Arq: done # A opcao -n eh para nao saltar linha

Ento vamos execut-lo:$ testefor1 ArqDoDOS.txt1:confuso:incusu:logado:musexc:musicas:musinc:muslist:$

Como voc viu o Shell transformou o astersco (que odeia ser chamado de asterstico) em uma lista de arquivos separados por espaos em branco. quando ofor

viu aquela lista, ele disse: Opa, lista separadas por espaos comigo

mesmo! O bloco de comandos a ser executado era somente o echo , que com a opo -n listou a varivel $Arq seguida de dois-pontos ( : ), sem saltar a linha. O cifro ( $ ) do final da linha da execuo o prompt. que permaneceu na mesma linha tambm em funo da opo -n . Outro exemplo simples (por enquanto):$ cat testefor2 #!/bin/bash # 2o. Prog didtico para entender o for

for Palavra in Papo de Botequim do echo $Palavra done

http://jneves.wordpress.com/[24/10/2011 17:12:51]

Julio Neves E executando vem:$ testefor2 Papo de Botequim

Como voc viu, este exemplo t