Curso de Shell Script 05/11

273 views

Published on

Você não aguenta mais aquele seu amigo usuário de Linux enchendo o seu saco com aquela história de que o sistema é fantástico e o Shell é uma ferramenta maravilhosa? A partir desta edição vai ficar mais fácil entender o porquê deste entusiasmo...

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

  • Be the first to like this

No Downloads
Views
Total views
273
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Curso de Shell Script 05/11

  1. 1. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER Curso de Shell Script Papo de Botequim V Blocos de código e laços (ou loops, como preferem alguns) Dave Hamilton - www.sxc.hu são o tema do mês em mais uma lição de nosso curso de Shell Script. Garçom, salta uma boa redondinha, que tô a fim de refrescar o pensamento! POR JULIO CEZAR NEVES – F ala cara! E as idéias estão em ordem? Já fundiu a cuca ou você ainda agüenta mais Shell? Até agora já vimos alguns blocos de código, como quando te mostrei um exemplo para fazer um cd para dentro Güento! Tô gostando muito! Gostei de um diretório: tanto que até caprichei no exercício Quadro 1: vira.sh $ cat vira.sh #!/bin/bash # que você passou. Lembra que você cd lmb 2> /dev/null || # vira - vi resguardando me pediu para fazer um programa { # arquivo anterior que recebe como parâmetro o nome mkdir lmb # Verifica se algum parâmetro foi de um arquivo e que quando execu- cd lmb # passado tado salva esse arquivo com o nome } if [ “$#” -ne 1 ] original seguido de um til (~) e o then abre dentro do vi? O fragmento contido entre as duas echo “Erro -> Uso: $0 U – Claro que lembro, me mostre e expli- chaves ({}) forma um bloco de código. <arquivo>” que como você fez. Também nesse exercício que acabamos exit 1 – Beleza, dá uma olhada no quadro 1 de ver, em que salvamos o arquivo antes fi – É, beleza! Mas me diz uma coisa: por de editá-lo, existem vários blocos de Arq=$1 que você terminou o programa com código compreendidos entre os coman- # Caso o arquivo não exista, não um exit 0? dos then e fi do if. Um bloco de código # há cópia a ser salva – Eu descobri que o número após o também pode estar dentro de um case if [ ! -f “$Arq” ] exit indica o código de retorno do ou entre um do e um done. then programa (o $?, lembra?) e assim, – Peraí, Julio, que do e done são esses? vi $Arq como a execução foi bem sucedida, Não me lembro de você ter falado exit 0 ele encerra com o $?=0. Porém, se nisso, e olha que estou prestando fi você observar, verá que caso o pro- muita atenção... # Se eu não puder alterar o grama não tenha recebido o nome do – Pois é, ainda não tinha falado porque #arquivo, vou usar o vi para que? arquivo ou caso o operador não tenha não havia chegado a hora certa. if [ ! -w “$Arq” ] permissão de gravação nesse arquivo, Todas as instruções de loop ou laço then o código de retorno ($?) seria dife- executam os comandos do bloco com- echo “Você não tem permissão U rente do zero. preendidos entre um do e um done. As de escrita em $Arq” – Grande garoto, aprendeu legal, mas é instruções de loop ou laço são for, while exit 2 bom deixar claro que exit 0, simples- e until , que serão explicadas uma a fi mente exit ou não colocar exit produ- uma a partir de hoje. # Já que está tudo OK, vou zem igualmente um código de retorno # salvar a cópia e chamar o vi ($?) igual a zero. Agora vamos falar O comando For cp -f $Arq $Arq~ sobre as instruções de loop ou laço, Se você está habituado a programar, vi $Arq mas antes vou passar o conceito de certamente já conhece o comando for, exit 0 bloco de código. mas o que você não sabe é que o for, ����������������������������� www.linuxmagazine.com.br edição 05 89 ��������������������������������������������������������������������������������
  2. 2. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim que é uma instrução intrínseca do Shell Então vamos executá-lo: $ echo “$IFS” | od -h (isso significa que o código fonte do 0000000 0920 0a0a comando faz parte do código fonte do $ testefor1 0000004 Shell, ou seja, em bom programês é um ArqDoDOS.txt1:confuso:incusu: built-in), é muito mais poderoso que os logado:musexc:musicas:musinc: Isto é, mandei a variável (protegida seus correlatos das outras linguagens. muslist:$ da interpretação do Shell pelas aspas) Vamos entender a sua sintaxe, pri- para um dump hexadecimal (od -h). O meiro em português e, depois, como Como você viu, o Shell transformou resultado pode ser interpretado com a funciona pra valer. Olhe só: o asterisco (que odeia ser chamado tabela abaixo: de asterístico) em uma lista de arqui- para var em val1 val2 ... valn vos separados por espaços em branco. Tabela 1: Resultado do od -h faça Quando o for viu aquela lista, disse: cmd1 “Opa, listas separadas por espaços é Valor Hexadecimal Significado cmd2 comigo mesmo!” 09 <TAB> cmdn O bloco de comandos a ser executado 20 <ESPAÇO> feito era somente o echo, que com a opção -n 0a <ENTER> listou a variável $Arq seguida de dois- Onde a variável var assume cada um pontos (:), sem saltar a linha. O cifrão dos valores da lista val1 val2 ... valn e, ($) do fi nal da linha da execução é o O último 0a foi proveniente do para cada um desses valores, executa o prompt, que permaneceu na mesma <ENTER> dado ao fi nal do comando. bloco de comandos formado por cmd1, linha também em função da opção -n. Para melhorar a explicação, vamos ver cmd2 e cmdn. Agora que já vimos o Outro exemplo simples (por enquanto): isso de outra forma: significado da instrução em português, vejamos a sintaxe correta: $ cat testefor2 $ echo “:$IFS:” | cat -vet #!/bin/bash : ^I$ for var in val1 val2 ... valn # 2o. Programa didático para :$ do # entender o for cmd1 for Palavra in Linux Magazine U No comando cat, a opção -e repre- cmd2 do Brasil senta o <ENTER> como um cifrão ($) cmdn do e a opção -t representa o <TAB> como done echo $Palavra um ^I. Usei os dois-pontos (:) para mos- done trar o início e o fi m do echo. E dessa Vamos aos exemplos, para entender forma, pudemos notar que os três carac- direito o funcionamento deste comando. E executando temos: teres estão presentes naquela variável. Vamos escrever um script para listar Agora veja você: traduzindo, IFS sig- todos os arquivos do diretório, separa- $ testefor2 nifica separador entre campos. Uma vez dos por dois-pontos, mas antes veja isso: Linux entendido isso, eu posso afi rmar que o Magazine comando for não usa apenas listas sepa- $ echo * do radas por espaços em branco, mas sim ArqDoDOS.txt1 confuso incusu Brasil pelo conteúdo da variável $IFS, cujo logado musexc musicas musinc valor padrão são os caracteres que aca- muslist Como você viu, esse exemplo é bamos de ver. Para comprovarmos isso, tão bobo e simples como o anterior, vamos continuar mexendo em nossa Isto é, o Shell viu o asterisco (*), mas serve para mostrar o comporta- CDTeca, escrevendo um script que expandiu-o com o nome de todos os mento básico do for. Veja só a força do recebe o nome do artista como parâme- arquivos do diretório e o comando echo comando: ainda estamos na primeira tro e lista as músicas que ele toca. Mas jogou-os para a tela separados por espa- possibilidade de sintaxe e já estou mos- primeiramente vamos ver como está o ços em branco. Visto isso, vamos resol- trando novas formas de usá-lo. Lá atrás nosso arquivo musicas: ver o problema a que nos propusemos: eu havia falado que o for usava listas separadas por espaços em branco, mas $ cat musicas $ cat testefor1 isso é uma meia-verdade, só para facili- album 1^Artista1~Musica1: U #!/bin/bash tar a compreensão. Na verdade, as listas Artista2~Musica2 # 1o. Programa didático para não são obrigatoriamente separadas por album 2^Artista3~Musica3: U # entender o for espaços. Mas antes de prosseguir, pre- Artista4~Musica4 for Arq in * ciso te mostrar como se comporta uma album 3^Artista5~Musica5: U do variável do sistema chamada de IFS, ou Artista6~Musica6 echo -n $Arq: Inter Field Separator Veja no exemplo a album 4^Artista7~Musica7: U done seguir seu conteúdo: Artista1~Musica3����������������������������� 90 edição 05 www.linuxmagazine.com.br��������������������������������������������������������������������������������
  3. 3. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Papo de Botequim LINUX USER album 5^Artista9~Musica9: U o $1 seria Perereca e o resto desse lindo $ listartista Artista1 Artista10~Musica10 nome seria ignorado na pesquisa. Musica1 Para que isso não ocorra, eu deveria Musica3 Em cima desse “leiaute” desenvolve- passar o nome do artista entre aspas mos o script a seguir: (”) ou trocar $1 por $* (que representa Veja uma segunda sintaxe para o for: todos os parâmetros passados), que é $ cat listartista a melhor solução, mas nesse caso eu for var #!/bin/bash teria que modificar a crítica dos parâ- do # Dado um artista, mostra as metros e o grep. A nova versão não cmd1 # suas músicas seria se eu passei um parâmetro, mas cmd2 if [ $# -ne 1 ] sim se passei pelo menos um parâ- cmdn then metro. Quanto ao grep, veja só o que done echo Você deveria ter U aconteceria após a substituição do $* passado um parâmetro pelos parâmetros: Ué, sem o in, como ele vai saber que exit 1 valor assumir? Pois é, né? Esta constru- fi echo “$ArtMus” | grep perereca U ção, à primeira vista, parece esquisita, IFS=” & peteleca mas é bastante simples. Neste caso, var :” assumirá um a um cada parâmetro pas- for ArtMus in $(cut -f2 -d^ U Isso gera um erro. O correto é: sado para o programa. Como exemplo musicas) para entender melhor, vamos fazer um do echo “$ArtMus” | grep -i U script que receba como parâmetro um echo “$ArtMus” | grep $1 && U “perereca & peteleca” monte de músicas e liste seus autores: echo $ArtMus | cut -f2 -d~ done Aqui adicionamos a opção -i para $ cat listamusica que a pesquisa ignorasse maiúsculas e #!/bin/bash O script, como sempre, começa tes- minúsculas. As aspas foram inseridas # Recebe parte dos nomes de tando se os parâmetros foram passados para que o nome do artista fosse visto # músicas como parâmetro e corretamente, em seguida o IFS foi confi- como uma só cadeia de caracteres. # lista os intérpretes. Se o gurado para <ENTER> e dois-pontos (:) Falta consertar o erro dele ter listado o # nome for composto, deve (como demonstram as aspas em linhas Artista10. O melhor é dizer ao grep que a # ser passado entre aspas. diferentes), porque é ele quem separa os cadeia de caracteres está no início (^) de # ex. “Eu não sou cachorro não” blocos Artistan~Musicam. Desta forma, $ArtMus e que logo após vem um til (~). É # “Churrasquinho de Mãe” a variável $ArtMus irá receber cada um preciso redirecionar a saída do grep para / # desses blocos do arquivo (repare que o dev/null para que os blocos não sejam lis- if [ $# -eq 0 ] for já recebe os registros sem o álbum tados. Veja a nova cara do programa: then em virtude do cut na sua linha). Caso echo Uso: $0 musica1 U encontre o parâmetro ($1) no bloco, o $ cat listartista [musica2] ... [musican] segundo cut listará somente o nome da #!/bin/bash exit 1 música. Vamos executar o programa: # Dado um artista, mostra as fi # suas musicas IFS=” $ listartista Artista1 # Versao 2 :” Artista1~Musica1 if [ $# -eq 0 ] for Musica Musica1 then do Artista1~Musica3 echo Voce deveria ter U echo $Musica Musica3 passado pelo menos um parametro Str=$(grep -i “$Musica” U Artista10~Musica10 exit 1 musicas) || Musica10 fi { IFS=” echo “ Não U Êpa! Aconteceram duas coisas inde- :” encontrada” sejáveis: os blocos também foram lista- for ArtMus in $(cut -f2 -d^ U continue dos, e a Musica10 idem. Além do mais, musicas) } o nosso arquivo de músicas está muito do for ArtMus in $(echo “$Str” U simples: na vida real, tanto a música echo “$ArtMus” | grep -i U | cut -f2 -d^) quanto o artista têm mais de um nome. “^$*~” > /dev/null && echo U do Suponha que o artista fosse uma dupla $ArtMus | cut -f2 -d~ echo “ $ArtMus” | U sertaneja chamada Perereca & Peteleca done grep -i “$Musica” | cut -f1 -d~ (não gosto nem de dar a idéia com receio done que isso se torne realidade). Nesse caso, O resultado é: done ����������������������������� www.linuxmagazine.com.br edição 05 91 ��������������������������������������������������������������������������������
  4. 4. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� LINUX USER Papo de Botequim Da mesma forma que os outros, come- Ou na forma mais completa do seq: Repare que o incremento saiu do çamos o exercício com uma crítica sobre corpo do for e passou para o bloco de os parâmetros recebidos, em seguida for i in $(seq 0 3 9) código; repare também que, quando fizemos um for em que a variável do usei o let, não foi necessário iniciali- $Musica receberá cada um dos parâme- echo -n “$i “ zar a variável $i. Veja só os comandos a tros passados, colocando em $Str todos done seguir, digitados diretamente no prompt, os álbuns que contêm as músicas dese- 0 3 6 9 para demonstrar o que acabo de falar: jadas. Em seguida, o outro for pega cada bloco Artista~Musica nos registros que A outra forma de fazer isso é com $ echo $j estão em $Str e lista cada artista que uma sintaxe muito semelhante ao for da $ let j++ toca aquela música. Vamos executar o linguagem C, como vemos a seguir: $ echo $j programa para ver se funciona mesmo: 1 for ((var=ini; cond; incr)) $ listamusica musica3 Musica4 U do Ou seja, a variável $j sequer existia e “Egüinha Pocotó” cmd1 no primeiro let assumiu o valor 0 (zero) musica3 cmd2 para, após o incremento, ter o valor 1. Artista3 cmdn Veja só como as coisas ficam simples: Artista1 done Musica4 for arq in * Artista4 Onde var=ini significa que a variá- do Egüinha Pocotó vel var começará de um valor inicial let i++ Não encontrada ini; cond significa que o loop ou laço for echo “$i -> $Arq” será executado enquanto var não atingir done A listagem ficou feinha porque ainda a condição cond e incr significa o incre- 1 -> ArqDoDOS.txt1 não sabemos formatar a saída; mas mento que a variável var sofrerá a cada 2 -> confuso qualquer dia desses, quando você sou- passada do loop. Vamos aos exemplos: 3 -> incusu ber posicionar o cursor, trabalhar com 4 -> listamusica cores etc., faremos esse programa nova- for ((i=1; i<=9; i++)) 5 -> listartista mente usando todas essas perfumarias. do 6 -> logado A esta altura dos acontecimentos, echo -n “$i “ 7 -> musexc você deve estar se perguntando: “E done 8 -> musicas aquele for tradicional das outras lingua- 1 2 3 4 5 6 7 8 9 9 -> musinc gens em que ele sai contando a partir 10 -> muslist de um número, com um determinado A variável i partiu do valor inicial 1, o 11 -> testefor1 incremento, até alcançar uma condi- bloco de código (aqui somente o echo) 12 -> testefor2 ção?”. E é aí que eu te respondo: “Eu será executado enquanto i for menor ou não te disse que o nosso for é mais por- igual (<=) a 9 e o incremento de i será – Pois é amigo, tenho certeza que você reta que o dos outros?” Para fazer isso, de 1 a cada passada do loop. já tomou um xarope do comando existem duas formas. Com a primeira Repare que no for propriamente dito for. Por hoje chega, na próxima vez sintaxe que vimos, como no exemplo: (e não no bloco de código) não coloquei em que nos encontrarmos falaremos um cifrão ($) antes do i e a notação sobre outras instruções de loop, mas for i in $(seq 9) para incrementar (i++) é diferente do eu gostaria que até lá você fi zesse um do que vimos até agora. O uso de parênte- pequeno script para contar a quanti- echo -n “$i “ ses duplos (assim como o comando let) dade de palavras de um arquivo texto, done chama o interpretador aritmético do cujo nome seria recebido como parâ- 1 2 3 4 5 6 7 8 9 Shell, que é mais tolerante. metro. Essa contagem tem que ser Só para mostrar como o let funciona feita com o comando for, para se habi- A variável i assumiu os valores intei- e a versatilidade do for, vamos fazer a tuar ao seu uso. Não vale usar o wc -w. ros entre 1 a 9 gerados pelo comando mesma coisa, mas omitindo a última Aê Chico! Traz a saideira! ■ seq e a opção -n do echo foi usada para parte do escopo do for, passando-a para não saltar uma linha a cada número lis- o bloco de código: Julio Cezar Neves é Analista de SOBRE O AUTOR tado. Ainda usando o for com seq: Suporte de Sistemas desde 1969 e tra- for ((; i<=9;)) balha com Unix desde 1980, quando for i in $(seq 4 9) do participou do desenvolvimento do do let i++ SOX, um sistema operacional similar echo -n “$i “ echo -n “$i “ ao Unix produzido pela Cobra Com- putadores. Pode ser contatado no done done e-mail julio.neves@gmail.com 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9����������������������������� 92 edição 05 www.linuxmagazine.com.br��������������������������������������������������������������������������������

×