��������������������������������������������������������������������������������������������������������������������������...
��������������������������������������������������������������������������������������������������������������������������...
��������������������������������������������������������������������������������������������������������������������������...
��������������������������������������������������������������������������������������������������������������������������...
��������������������������������������������������������������������������������������������������������������������������...
Upcoming SlideShare
Loading in...5
×

Curso de Shell Script 03/11

113

Published on

Um chopinho, um aperitivo e o papo continua. Desta vez vamos aprender alguns comandos de manipulação de cadeias de caracteres, que serão muito úteis na hora de incrementar nossa “CDteca”.

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
113
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Curso de Shell Script 03/11

  1. 1. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER Curso de Shell Script Papo de botequim III Um chopinho, um aperitivo e o papo continua. Desta vez vamos aprender alguns comandos de manipulação de cadeias de caracteres, que serão muito úteis na hora de incrementar nossa “CDteca”. POR JULIO CEZAR NEVES G arçon! traga dois chopes por favor que hoje eu vou ter que falar muito. Primeiro quero mostrar uns programinhas simples de usar e muito úteis, como o cut, que Então, recapitulando, o layout do arquivo é o seguinte: nome do álbum^intérprete1~nome da música1:...: intérpreten~nome da músican, isto é, o nome do álbum será separado por um Artista2 Artista4 Artista6 Artista8 é usado para cortar um determinado circunflexo (^) do resto do registro, que Para entender melhor isso, vamos anali- pedaço de um arquivo. A sintaxe e é formado por diversos grupos compos- sar a primeira linha de musicas: alguns exemplos de uso podem ser vis- tos pelo intérprete de cada música do tos no Quadro 1: CD e a respectiva música interpretada. $ head -1 musicas Como dá para ver, existem quatro Estes grupos são separados entre si por album 1^Artista1~Musica1: U sintaxes distintas: na primeira (-c 1-5) dois-pontos (:) e o intérprete será sepa- Artista2~Musica2 especifiquei uma faixa, na segunda rado do nome da música por um til (~). (-c -6) especifiquei todo o texto até Então, para pegar os dados referentes Então observe o que foi feito: uma posição, na terceira (-c 4-) tudo de a todas as segundas músicas do arquivo uma determinada posição em diante e musicas, devemos digitar: album 1^Artista1~Musica1: U na quarta (-c 1,3,5,7,9), só as posições Artista2~Musica2 determinadas. A última possibilidade $ cut -f2 -d: musicas (-c -3,5,8-) foi só para mostrar que pode- Artista2~Musica2 Desta forma, no primeiro cut o primeiro mos misturar tudo. Artista4~Musica4 campo do delimitador (-d) dois-pon- Mas não pense que acabou por aí! Artista6~Musica5 tos (:) é album 1^Artista1~Musica1 e o Como você deve ter percebido, esta Artista8~Musica8@10_L: segundo, que é o que nos interessa, é forma de cut é muito útil para lidar com Artista2~Musica2. Vamos então ver o arquivos com campos de tamanho fi xo, Ou seja, cortamos o segundo campo que aconteceu no segundo cut: mas atualmente o que mais existe são z(-f de field, campo em inglês) delimi- arquivos com campos de tamanho vari- tado (-d) por dois-pontos (:). Mas, se Artista2~Musica2 ável, onde cada campo termina com um quisermos somente os intérpretes, deve- delimitador. Vamos dar uma olhada no mos digitar: Agora, primeiro campo do delimitador arquivo musicas que começamos a pre- (-d) til (~), que é o que nos interessa, parar na última vez que viemos aqui no $ cut -f2 -d: musicas | cut U é Artista2 e o segundo é Musica2. Se botequim. Veja o Quadro 2. -f1 -d~ o raciocínio que fizemos para a pri- ����������������������������� www.linuxmagazine.com.br Outubro 2004 85 ��������������������������������������������������������������������������������
  2. 2. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim Quadro 1 – O comando cut meira linha for aplicado ao restante do arquivo, chegaremos à resposta ante- posta a um exercício prático, valendo nota, que passei ele me entregou um riormente dada. Outro comando muito script com todos os comandos sepa- A sintaxe do cut é: cut -c PosIni-PosFim interessante é o tr que serve para subs- rados por ponto-e-vírgula (lembre-se [arquivo], onde PosIni é a posição inicial, e tituir, comprimir ou remover caracteres. que o ponto-e-vírgula serve para sepa- PosFim a posição final. Veja os exemplos: Sua sintaxe segue o seguinte padrão: rar diversos comandos em uma mesma linha). Vou dar um exemplo simplifi- $ cat numeros tr [opções] cadeia1 [cadeia2] cado, e idiota, de um script assim: 1234567890 0987654321 O comando copia o texto da entrada $ cat confuso 1234554321 padrão (stdin), troca as ocorrência dos echo leia Programação Shell U 9876556789 caracteres de cadeia1 pelo seu corres- Linux do Julio Cezar Neves U pondente na cadeia2 ou troca múltiplas > livro;cat livro;pwd;ls;rm U $ cut -c1-5 numeros ocorrências dos caracteres de cadeia1 -f livro2>/dev/null;cd ~ 12345 por somente um caracter, ou ainda 09876 caracteres da cadeia1. As principais Eu executei o programa e ele funcionou: 12345 opções do comando são mostradas na 98765 Tabela 1. $ confuso Primeiro veja um exemplo bem bobo: leia Programação Shell Linux U $ cut -c-6 numeros do Julio Cezar Neves 123456 $ echo bobo | tr o a /home/jneves/LM 098765 baba confuso livro musexc musicas 123455 musinc muslist numeros 987655 Isto é, troquei todas as ocorrências da letra o pela letra a. Suponha que em Mas nota de prova é coisa séria (e nota $ cut -c4- numeros determinado ponto do meu script eu de dólar é mais ainda) então, para 4567890 peça ao operador para digitar s ou n entender o que o aluno havia feito, o 7654321 (sim ou não), e guardo sua resposta chamei e em sua frente digitei: 4554321 na variável $Resp. Ora, o conteúdo de 6556789 $Resp pode conter letras maiúsculas $ tr ”;” ”n” < confuso ou minúsculas, e desta forma eu teria echo leia Programação Shell U $ cut -c1,3,5,7,9 numeros que fazer diversos testes para saber se Linux do Julio Cezar Neves 13579 a resposta dada foi S, s, N ou n. Então o pwd 08642 melhor é fazer: cd ~ 13542 ls -l 97568 $ Resp=$(echo $Resp | tr SN sn) rm -f lixo 2>/dev/null $ cut -c -3,5,8- numeros e após este comando eu teria certeza O cara ficou muito desapontado, porque 1235890 de que o conteúdo de $Resp seria um em dois ou três segundos eu desfi z a 0986321 s ou um n. Se o meu arquivo ArqEnt gozação que ele perdeu horas para fazer. 1235321 está todo em letras maiúsculas e desejo Mas preste atenção! Se eu estivesse em 9875789 passá-las para minúsculas eu faço: uma máquina Unix, eu teria digitado: $ tr A-Z a-z < ArqEnt > / tmp/$$ $ tr ”;” ”012” < confuso Quadro 2 – O arquivo $ mv -f /tmp/$$ ArqEnt musicas Agora veja a diferença entre o resultado Note que neste caso usei a notação A- de um comando date executado hoje e Z para não escrever ABCD…YZ. Outro outro executado há duas semanas: $ cat musicas tipo de notação que pode ser usada são album 1^Artista1~Musica1:U as escape sequences (como eu traduzi- Sun Sep 19 14:59:54 2004 Artista2~Musica2 ria? Seqüências de escape? Meio sem Sun Sep 5 10:12:33 2004 album 2^Artista3~Musica3:U sentido, né? Mas vá lá…) que também Artista4~Musica4 são reconhecidas por outros comandos Notou o espaço extra após o “Sep” na album 3^Artista5~Musica5:U e também na linguagem C, e cujo signi- segunda linha? Para pegar a hora eu Artista6~Musica5 ficado você verá na Tabela 2: deveria digitar: album 4^Artista7~Musica7:U Deixa eu te contar um “causo”: um Artista8~Musica8 aluno que estava danado comigo resol- $ date | cut -f 4 -d ’ ’ veu complicar minha vida e como res- 14:59:54����������������������������� 86 Outubro 2004 www.linuxmagazine.com.br��������������������������������������������������������������������������������
  3. 3. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER Mas há duas semanas ocorreria o Bem a opção -d do tr remove do arquivo E veja também o date: seguinte: todas as ocorrências do caractere espe- cificado. Desta forma eu removi os $ date $ date | cut -f 4 -d ’ ’ caracteres indesejados, salvei o texto Mon Sep 20 10:47:19 BRT 2004 5 em um arquivo temporário e posterior- mente renomeei-o para o nome original. Repare que o mês e o dia estão no Isto porque existem 2 caracteres em Uma observação: em um sistema Unix mesmo formato em ambos os coman- branco antes do 5 (dia). Então o ideal eu deveria digitar: dos. Ora, se em algum registro do who seria transformar os espaços em branco eu não encontrar a data de hoje, é sinal consecutivos em somente um espaço $ tr -d ’015’ < ArqDoDOS.U que o usuário está “logado” há mais para poder tratar os dois resultados do txt > /tmp/$$ de um dia, já que ele não pode ter se comando date da mesma forma, e isso “logado” amanhã… Então vamos guar- se faz assim: Uma dica: o problema com os termina- dar o pedaço que importa da data de dores de linha (CR/LF) só aconteceu hoje para depois procurá-la na saída do $ date | tr -s ” ” porque a transferência do arquivo foi comando who: Sun Sep 5 10:12:33 2004 feita no modo binário (ou image), Se antes da transmissão do arquivo tivesse $ Data=$(date | cut -f 2-3 U E agora eu posso cortar: sido estipulada a opção ascii do ftp, isto -d’ ’) não teria ocorrido. $ date | tr -s ” ” | cut -f 4 U – Olha, depois desta dica tô começando a Eu usei a construção $(...), para prio- -d ” ” gostar deste tal de shell, mas ainda tem rizar a execução dos comandos antes 10:12:33 muita coisa que não consigo fazer. de atribuir a sua saída à variável Data. – Pois é, ainda não te falei quase nada Vamos ver se funcionou: Olha só como o Shell está quebrando o sobre programação em shell, ainda galho. Veja o conteúdo de um arquivo tem muita coisa para aprender, mas $ echo $Data baixado de uma máquina Windows: com o que aprendeu, já dá para resol- Sep 20 ver muitos problemas, desde que você $ cat -ve ArqDoDOS.txt adquira o “modo shell de pensar”. Você Beleza! Agora, o que temos que fazer é Este arquivo^M$ seria capaz de fazer um script que diga procurar no comando who os registros foi gerado pelo^M$ quais pessoas estão “logadas” há mais que não possuem esta data. DOS/Win e foi^M$ de um dia no seu servidor? baixado por um^M$ – Claro que não! Para isso seria necessá- – Ah! Eu acho que estou entendendo! ftp mal feito.^M$ rio eu conhecer os comandos condicio- Você falou em procurar e me ocorreu o nais que você ainda não me explicou comando grep, estou certo? Dica: a opção -v do cat mostra os carac- como funcionam. - Deixa eu tentar – Certíssimo! Só que eu tenho que usar o teres de controle invisíveis, com a nota- mudar um pouco a sua lógica e trazê- grep com aquela opção que ele só lista ção ^L, onde ^ é a tecla Control e L é la para o “modo shell de pensar”, mas os registros nos quais ele não encon- a respectiva letra. A opção -e mostra o antes é melhor tomarmos um chope. trou a cadeia. Você se lembra que fi nal da linha como um cifrão ($). Agora que já molhei a palavra, vamos opção é essa? Isto ocorre porque no DOS o fi m dos resolver o problema que te propus. Veja – Claro, a -v… registros é indicado por um Carriage como funciona o comando who: – Isso! Tá ficando bom! Vamos ver: Return (r – Retorno de Carro, CR) e um Line Feed (f – Avanço de Linha, ou $ who $ who | grep -v ”$Data” LF). No Linux porém o fi nal do regis- jneves pts/ U jneves pts/ U tro é indicado somente pelo Line Feed. 1 Sep 18 13:40 1 Sep 18 13:40 Vamos limpar este arquivo: rtorres pts/ U 0 Sep 20 07:01 Se eu quisesse um pouco mais de perfu- $ tr -d ’r’ < ArqDoDOS.txt > /tmp/$$ rlegaria pts/ U maria eu faria assim: $ mv -f /tmp/$$ ArqDoDOS.txt 1 Sep 20 08:19 lcarlos pts/ U $ who | grep -v ”$Data” |U Agora vamos ver o que aconteceu: 3 Sep 20 10:01 cut -f1 -d ’ ’ jneves $ cat -ve ArqDoDOS.txt Tabela 1 – O comando tr Este arquivo$ Opção Significado Viu? Não foi necessário usar comando foi gerado pelo$ condicional, até porque o nosso -s Comprime n ocorrências de DOS/Rwin e foi$ cadeia1 em apenas uma comando condicional, o famoso if, não baixado por um$ testa condição, mas sim instruções. -d Remove os caracteres de cadeia1 ftp mal feito.$ Mas antes veja isso: ����������������������������� www.linuxmagazine.com.br Outubro 2004 87 ��������������������������������������������������������������������������������
  4. 4. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim $ ls musicas Tabela 2 /dev/null musicas Seqüência Significado Octal then $ echo $? t Tabulação 011 echo Usuario ’$1’ já U 0 n Nova linha 012 existe $ ls ArqInexistente <ENTER> else ls: ArqInexistente: No such U v Tabulação 013 if useradd $1 file or directory Vertical then $ echo $? f Nova 014 echo Usuário ’$1’ U 1 Página incluído em /etc/passwd $ who | grep jneves r Início da 015 else jneves pts/1 Sep 18 U linha <^M> echo ”Problemas no U Uma barra 0134 13:40 (10.2.4.144) cadastramento. Você é root?” invertida $ echo $? fi 0 fi $ who | grep juliana já existe $ echo $? else Vamos testá-lo como um usuário normal : 1 if useradd $1 then $ incusu ZeNinguem O que é que esse $? faz aí? Algo come- echo Usuário ’$1’ U ./incusu[6]: useradd: not found çado por cifrão ($) parece ser uma vari- incluído em /etc/passwd Problemas no cadastramento. U ável, certo? Sim é uma variável que else Você é root? contém o código de retorno da última echo ”Problemas no U instrução executada. Posso te garan- cadastramento. Você é root?” Aquela mensagem de erro não deveria tir que se esta instrução foi bem suce- fi aparecer! Para evitar isso, devemos dida, $? terá o valor zero, caso contrário fi redirecionar a saída de erro (stderr) do seu valor será diferente de zero. O que comando useradd para /dev/null. A ver- nosso comando condicional (if) faz é Repare que o if está testando direto o são fi nal fica assim: testar esta variável. Então vamos ver a comando grep e esta é a sua fi nalidade. sua sintaxe: Caso o if seja bem sucedido, ou seja, o $ cat incusu usuário (cujo nome está em $1) foi #!/bin/bash if cmd encontrado em /etc/passwd, os coman- # Versão 3 then dos do bloco do then serão executados if grep ^$1 /etc/passwd > U cmd1 (neste exemplo, apenas o echo). Caso /dev/null cmd2 contrário, as instruções do bloco do else then cmdn serão executadas, quando um novo if echo Usuario ’$1’ já U else testa se o comando useradd foi execu- existe cmd3 tado a contento, criando o registro do else cmd4 usuário em /etc/passwd, ou exibindo if useradd $1 2> /dev/null cmdm uma mensagem de erro, caso contrário. then fi Executar o programa e passe como echo Usuário ’$1’ U parâmetro um usuário já cadastrado: incluído em /etc/passwd Ou seja, caso comando cmd tenha sido else executado com sucesso, os comandos $ incusu jneves echo ”Problemas no U do bloco do then (cmd1, cmd2 e cmdn) jneves:x:54002:1001:Julio Neves: U cadastramento. Você é root?” serão executados, caso contrário, os /home/jneves:/bin/ U fi comandos do bloco opcional do else bash fi (cmd3, cmd4 e cmdm) serão executados. Usuario ’jneves’ ja existe O bloco do if é terminando com um fi. Depois disso, vejamos o comportamento Vamos ver na prática como isso fun- No exemplo dado, surgiu uma linha do programa, se executado pelo root: ciona, usando um script que inclui usu- indesejada, ela é a saída do comando ários no arquivo /etc/passwd: grep. Para evitar que isso aconteça, $ incusu botelho devemos desviar a saída para /dev/null. Usuário ’botelho’ incluido em U $ cat incusu O programa fica assim: /etc/passwd #!/bin/bash # Versão 1 $ cat incusu E novamente: if grep ^$1 /etc/passwd #!/bin/bash then # Versão 2 $ incusu botelho echo Usuario ’$1’U if grep ^$1 /etc/passwd > U Usuário ’botelho’ já existe����������������������������� 88 Outubro 2004 www.linuxmagazine.com.br��������������������������������������������������������������������������������
  5. 5. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER Lembra que eu falei que ao longo dos no início da cadeia e cifrão ($) no fi m, Como você viu, o programa melho- nossos papos e chopes os nossos pro- servem para testar se o parâmetro (o rou um pouquinho, mas ainda não está gramas iriam se aprimorando? Então álbum e seus dados) é exatamente igual pronto. À medida que eu te ensinar a vejamos agora como podemos melhorar a algum registro já existente. Vamos programar em shell, nossa CDteca vai o nosso programa para incluir músicas executar nosso programa novamente, ficar cada vez melhor. na "CDTeca": mas desta vez passamos como parâme- – Entendi tudo que você me explicou, tro um álbum já cadastrado, pra ver o mas ainda não sei como fazer um if $ cat musinc que acontece: para testar condições, ou seja o uso #!/bin/bash normal do comando. # Cadastra CDs (versao 3) $ musinc ”album 4^Artista7~ U – Para isso existe o comando test, que # Musica7:Artista8~Musica8” testa condições. O comando if testa if grep ”^$1$” musicas > U Este álbum já está cadastrado o comando test. Como já falei muito, /dev/null preciso de uns chopes para molhar a then E agora um não cadastrado: palavra. Vamos parar por aqui e na echo Este álbum já está U próxima vez te explico direitinho o cadastrado $ musinc ”album 5^Artista9~ U uso do test e de diversas outras sinta- else Musica9:Artista10~Musica10” xes do if. echo $1 >> musicas $ cat musicas – Falou! Acho bom mesmo porque eu sort musicas -o musicas album 1^Artista1~Musica1: U também já tô ficando zonzo e assim fi Artista2~Musica2 tenho tempo para praticar esse monte album 2^Artista3~Musica3: U de coisas que você me falou hoje. Como você viu, é uma pequena evolu- Artista4~Musica4 Para fi xar o que você aprendeu, tente ção em relação à versão anterior. Antes album 3^Artista5~Musica5: U fazer um scriptizinho para informar se de incluir um registro (que na versão Artista6~Musica5 um determinado usuário, cujo nome anterior poderia ser duplicado), testa- album 4^Artista7~Musica7: U será passado como parâmetro, está mos se o registro começa (^) e termina Artista8~Musica8 “logado” no sistema ou não. ($) de forma idêntica ao parâmetro album 5^Artista9~Musica9: U – Aê Chico! traz mais dois chopes pra álbum passado ($1). O circunflexo (^) Artista10~Musica10 mim por favor… ■ ����������������������������� www.linuxmagazine.com.br Outubro 2004 89 ��������������������������������������������������������������������������������

×