You are here:
Wiki-SL
>
TWikiBar Web
>
BatePapos
>
TWikiBarPapo003
(01 Aug 2009,
BrSalgado
)
(raw view)
E
dit
A
ttach
---+!! Papo de Botequim Parte III<!--pula duas linhas--> %TOC% - Garçon, traga dois chopes por favor que hoje eu vou ter que falar muito. ---++ Trabalhando com cadeias Pelo título acima não pense você que vou lhe ensinar a ser carcereiro! Estou me referindo a cadeia de caracteres! ---+++ O Comando cut (que não é a central de trabalhadores) <!--pula duas linhas--> Primeiro quero te mostrar, de forma eminentemente prática uma instrução simples de usar e muito útil: o comando =cut=, Esta instrução é usada para cortar um determinado pedaço de um arquivo e tem duas formas distintas de uso ---++++ O comando =cut= com a opção -c Com esta opção, o comando tem a seguinte sintaxe:%BR% <noautolink> =cut -c PosIni-PosFim [arquivo]= </noautolink> Onde:%BR% <noautolink> =PosIni = Posição inicial= %BR% =PosFim = Posição final= </noautolink> %TERMINAL_INI% $ cat numeros %OUT_INI%1234567890 0987654321 1234554321 9876556789%OUT_FIM% $ cut -c1-5 numeros %OUT_INI%12345 09876 12345 98765%OUT_FIM% $ cut -c-6 numeros%OUT_INI% 123456 098765 123455 987655%OUT_FIM% $ cut -c4- numeros%OUT_INI% 4567890 7654321 4554321 6556789%OUT_FIM% $ cut -c1,3,5,7,9 numeros%OUT_INI% 13579 08642 13542 97568%OUT_FIM% $ cut -c -3,5,8- numeros%OUT_INI% 1235890 0986321 1235321 9875789%OUT_FIM% %TERMINAL_FIM% 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 posição, na terceira =(-c 4-)= de uma determinada posição em diante e na quarta =(-c 1,3,5,7,9)=, determinadas posições. A última =(-c -3,5,8-)= foi só para mostrar que podemos misturar tudo. ---++++ O comando =cut= com a opção -f Mas não 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 são arquivos com campos de tamanho variáveis, onde cada campo termina com um delimitador. Vamos dar uma olhada no arquivo =musicas= que começamos a preparar no nosso papo na última vez que viemos aqui no botequim. %TERMINAL_INI% $ cat musicas%OUT_INI% album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8%OUT_FIM% %TERMINAL_FIM% Então, recapitulando, o seu _"leiaute"_ é o seguinte:%BR% =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 intérprete de cada música do CD e a respectiva música interpretada. Estes grupos são separados entre si por dois-pontos (=:=) e internamente, o nome do intérprete será separado por um til (=~=) do nome da música. Então para pegarmos os dados referentes a todas as segundas músicas do arquivo =musicas=, devemos fazer: %TERMINAL_INI% $ cut -f2 -d: musicas%OUT_INI% Artista2~Musica2 Artista4~Musica4 Artista6~Musica5 Artista8~Musica8%OUT_FIM% %TERMINAL_FIM% Ou seja, cortamos o segundo campo (=-f= de _field_ em inglês) delimitado (=-d=) por dois-pontos (=:=). Mas, se quisermos somente os intérpretes, devemos fazer: %TERMINAL_INI% $ cut -f2 -d: musicas | cut -f1 -d~%OUT_INI% Artista2 Artista4 Artista6 Artista8%OUT_FIM% %TERMINAL_FIM% Para entender isso, vamos pegar a primeira linha de =musicas=: %TERMINAL_INI% $ head -1 musicas%OUT_INI% album 1^Artista1~Musica1:Artista2~Musica2%OUT_FIM% %TERMINAL_FIM% Então observe o que foi feito: Delimitador do primeiro =cut= (=:=) =%T1%album 1^Artista1~Musica1%T0%:%T2%Artista2~Musica2%T0%= Desta forma, no primeiro =cut=, o primeiro campo do delimitador (=-d=) dois-pontos (=:=) é %T1%album 1^Artista1~Musica1%T0% e o segundo, que é o que nos interessa, é %T2%Artista2~Musica2%T0%. Vamos então ver o que aconteceu no segundo =cut=: Novo delimitador (=~=) =%T1%Artista2%T0%~%T2%Musica2%T0%= Agora, primeiro campo do delimitador (=-d=) til (=~=), que é o que nos interessa, é %T1%Artista2%T0% e o segundo é %T2%Musica2%T0%. Se o raciocínio que fizemos para a primeira linha for aplicado no restante do arquivo, chegaremos à resposta anteriormente dada. ---+++ Se tem cut tem paste Como já era de se esperar, o comando =paste= serve para colar, só que aqui no _Shell_ o que ele cola são arquivos. Só para começar a entendê-lo, vamos fazer assim:: <verbatim> paste arq1 arq2 </verbatim> Desta forma ele mandará para a saída padrão (=stdout=) cada um dos registros de =arq1= ao lado dos registros de =arq2= correspondentes e caso nenhum delimitador seja especificado, ele usará por _default_ o =<TAB>=. O paste é um comando pouco usado por sua sintaxe ser pouco conhecida. Vamos brincar com 2 arquivos criados da seguinte forma: %TERMINAL_INI% $ seq 10 > inteiros $ seq 2 2 10 > pares %TERMINAL_FIM% Para ver o conteúdo dos arquivos criados, vamos usar o =paste= na sua forma careta que mostramos acima: %TERMINAL_INI% $ paste inteiros pares%OUT_INI% 1 2 2 4 3 6 4 8 5 10 6 7 8 9 10%OUT_FIM% %TERMINAL_FIM% ---++++ Quem está em pé, deita Agora vamos transformar a coluna do =pares= em linha: %TERMINAL_INI% $ paste -s pares%OUT_INI% 2 4 6 8 10%OUT_FIM% %TERMINAL_FIM% ---++++ Usando separadores Como já foi dito, o separador _default_ do =paste= é o =<TAB>=, mas isso pode ser alterado com a opção =-d=. Então para calcular a soma do conteúdo de =pares= primeiramente faríamos: %TERMINAL_INI% $ paste -s -d'+' pares # também poderia ser -sd'+'%OUT_INI% 2+4+6+8+10%OUT_FIM% %TERMINAL_FIM% e depois passaríamos esta linha para a calculadora (=bc=) e então ficaria: %TERMINAL_INI% $ paste -sd'+' pares | bc%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% Assim sendo, para calcular o fatorial do número contido em =$Num=, basta: %TERMINAL_INI% $ seq $Num | paste -sd'*' | bc %TERMINAL_FIM% Com o comando =paste= você também pode montar formatações exóticas como esta a seguir: %TERMINAL_INI% $ ls | paste -s -d'\t\t\n'%OUT_INI% arq1 arq2 arq3 arq4 arq5 arq6%OUT_FIM% %TERMINAL_FIM% O que aconteceu foi o seguinte: foi especificado para o comando =paste= que ele transformaria linhas em colunas (pela opção =-s=) e que os seus separadores (é...! Ele aceita mais de um, mas somente um após cada coluna criada pelo comando) seriam uma =<TAB>=, outra =<TAB>= e um =<ENTER>=, gerando desta forma a saída tabulada em 3 colunas. Agora que você já entendeu isto, veja como fazer a mesma coisa, porém de forma mais fácil e menos bizarra e tosca, usando o mesmo comando mas com a seguinte sintaxe: %TERMINAL_INI% $ ls | paste - - -%OUT_INI% arq1 arq2 arq3 arq4 arq5 arq6%OUT_FIM% %TERMINAL_FIM% E isto acontece porque se ao invés de especificarmos os arquivos colocarmos o sinal de menos (=-=), o comando =paste= os substitui pela saída ou entrada padrão conforme o caso. No exemplo anterior os dados foram mandados para a saída padrão (=stdout=), porque o _pipe_ (=|=) estava desviando a saída do =ls= para a entrada padrão (=stdin=) do =paste=, mas veja o exemplo a seguir: %TERMINAL_INI% $ cat arq1%OUT_INI% predisposição privilegiado profissional%OUT_FIM% $ cat arq2%OUT_INI% encher mário motor%OUT_FIM% $ cut -c-3 arq1 | paste -d "" - arq2%OUT_INI% preencher primário promotor%OUT_FIM% %TERMINAL_FIM% Neste caso, o =cut= devolveu as três primeiras letras de cada registro de =arq1=, o =paste= foi montado para não ter separador (=-d""=) e receber a entrada padrão (desviada pelo _pipe_) no traço (=-=) gerando a saída juntamente com =arq2=. ---+++ O Comando tr Outro comando muito interessante é o tr que serve para substituir, comprimir ou remover caracteres. Sua sintaxe segue o seguinte padrão: <verbatim> tr [opções] cadeia1 [cadeia2] </verbatim> O comando =tr= copia o texto da entrada padrão (_stdin_), troca as ocorrência dos caracteres de =cadeia1= pelo seu correspondente na =cadeia2= ou troca múltiplas ocorrências dos caracteres de =cadeia1= por somente um caracter, ou ainda remove caracteres da =cadeia1=. As principais =opções= do comando são: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Principais Opções do comando tr* || | *Opção* | *Significado* | | -s | Comprime n ocorrências de cadeia1 em apenas uma | | -d | Remove os caracteres de cadeia1 | </center> ---++++ Trocando caracteres com =tr= Primeiro vou te dar um exemplo bem bobo: %TERMINAL_INI% $ echo bobo | tr o a%OUT_INI% baba%OUT_FIM% %TERMINAL_FIM% Isto é, troquei todas as ocorrências da letra =o= pela letra =a=. Suponha que em um determinado ponto do meu _script_ eu peça ao operador para teclar =s= ou =n= (sim ou não), e guardo sua resposta na variável =$Resp=. Ora o conteúdo de =$Resp= pode estar com letra maiúscula ou minúscula, e desta forma eu teria que fazer diversos testes para saber se a resposta dada foi =S=, =s=, =N= ou =n=. Então o melhor é fazer: %TERMINAL_INI% $ Resp=$(echo $Resp | tr SN sn) %TERMINAL_FIM% e após este comando eu teria certeza que o conteúdo de =$Resp= seria um =s= ou um =n=. Se o meu arquivo =ArqEnt= está todo escrito com letras maiúsculas e desejo passá-las para minúsculas eu faço: <noautolink> %TERMINAL_INI% $ tr A-Z a-z < ArqEnt > /tmp/$$ $ mv -f /tmp/$$ ArqEnt %TERMINAL_FIM% </noautolink> Note que neste caso usei a notação =A-Z= para não escrever =ABCD...YZ=. Outro tipo de notação que pode ser usada são as _escape sequences_ (prefiro escrever no bom e velho português, mas nesse caso como eu traduziria? Seqüências de escape? Meio sem sentido, né? Mas vá lá...) que também são reconhecidas por outros comandos e também na linguagem C, e cujo significado você verá a seguir: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Escape Sequences* ||| | *Seqüência* | *Significado* | *Octal* | | \t | Tabulação | \011 | | \n | Nova linha <ENTER> | \012 | | \v | Tabulação Vertical | \013 | | \f | Nova Página | \014 | | \r | Início da linha <^M> | \015 | | \\ | Uma barra invertida | \0134 | </center> ---++++ Removendo caracteres com =tr= Então deixa eu te contar um "causo": um aluno que estava danado comigo, resolveu complicar a minha vida e em um exercício prático valendo nota que passei para ser feito no computador, me entregou o _script_ com todos os comandos separados por ponto-e-vírgula (lembra que eu disse que o ponto-e-vírgula servia para separar diversos comandos em uma mesma linha?). Vou dar um exemplo simplificado e idiota de uma "tripa" assim: %TERMINAL_INI% $ cat confuso%OUT_INI% echo leia Programação Shell Linux do Julio Cezar Neves > livro;cat livro;pwd;ls;rm -f lixo 2>/dev/null;cd ~%OUT_FIM% %TERMINAL_FIM% Eu executava o programa e ele funcionava: %TERMINAL_INI% $ confuso%OUT_INI% leia Programação Shell Linux do Julio Cezar Neves /home/jneves/LM confuso livro musexc musicas musinc muslist numeros%OUT_FIM% %TERMINAL_FIM% Mas nota de prova é coisa séria (e nota de dólar é mais ainda :)) então, para entender o que o aluno havia feito, o chamei e em sua frente executei o seguinte comando: %TERMINAL_INI% $ tr ";" "\n" < confuso%OUT_INI% echo leia Programação Shell Linux do Julio Cezar Neves pwd ls rm -f lixo 2>/dev/null%OUT_FIM% cd ~ %TERMINAL_FIM% O cara ficou muito desapontado, porque em 2 ou 3 segundos eu desfiz a gozação que ele perdera horas para fazer.%BR% Mas preste atenção! Se eu estivesse em uma máquina com Unix, eu teria feito: %TERMINAL_INI% $ tr ";" "\012" < confuso %TERMINAL_FIM% ---++++ Xpremendo com =tr= Agora veja a diferença entre os dois comandos =date=: o que fiz hoje e outro que foi executado há duas semanas: %TERMINAL_INI% $ date # Hoje%OUT_INI% Sun Sep 19 14:59:54 2004%OUT_FIM% $ date # Há duas semanas%OUT_INI% Sun Sep 5 10:12:33 2004%OUT_FIM% %TERMINAL_FIM% Para pegar a hora eu deveria fazer: %TERMINAL_INI% $ date | cut -f 4 -d ' '%OUT_INI% 14:59:54%OUT_FIM% %TERMINAL_FIM% Mas duas semanas antes ocorreria o seguinte: %TERMINAL_INI% $ date | cut -f 4 -d ' '%OUT_INI% 5%OUT_FIM% %TERMINAL_FIM% Mas observe porque: %TERMINAL_INI% $ date # Há duas semanas%OUT_INI% Sun Sep 5 10:12:33 2004%OUT_FIM% %TERMINAL_FIM% Como você pode notar, existem 2 caracteres em branco antes do =5= (dia), o que estraga tudo porque o terceiro pedaço está vazio e o quarto é o dia (=5=). Então o ideal seria comprimir os espaços em brancos sucessivos em somente um espaço para poder tratar as duas cadeias resultantes do comando =date= da mesma forma, e isso se faz assim: %TERMINAL_INI% $ date | tr -s " "%OUT_INI% Sun Sep 5 10:12:33 2004%OUT_FIM% %TERMINAL_FIM% Como você pode ver não existem mais os dois espaços, então agora eu poderia cortar: %TERMINAL_INI% $ date | tr -s " " | cut -f 4 -d " "%OUT_INI% 10:12:33%OUT_FIM% %TERMINAL_FIM% Olha só como o _Shell_ já está quebrando o galho. Veja este arquivo que foi baixado de uma máquina com aquele sistema operacional que pega vírus: <noautolink> %TERMINAL_INI% $ cat -ve ArqDoDOS.txt%OUT_INI% Este arquivo^M$ foi gerado pelo^M$ DOS/Rwin e foi^M$ baixado por um^M$ ftp mal feito.^M$%OUT_FIM% %TERMINAL_FIM% </noautolink> E agora eu quero te dar duas dicas: %DICA_INI% *Dica #1* - A opção =-v= do =cat= mostra os caracteres de controle invisíveis, com a notação =^L=, onde =^= é a tecla control e =L= é a respectiva letra. A opção =-e= mostra o final da linha como um cifrão (=$=). %DICA_FIM% %DICA_INI% *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 porém o final do registro tem somente o _line-feed_. %DICA_FIM% Vamos então limpar este arquivo. <noautolink> %TERMINAL_INI% $ tr -d '\r' < ArqDoDOS.txt > /tmp/$$ $ mv -f /tmp/$$ ArqDoDOS.txt %TERMINAL_FIM% </noautolink> Agora vamos ver o que aconteceu: <noautolink> %TERMINAL_INI% $ cat -ve ArqDoDOS.txt%OUT_INI% Este arquivo$ foi gerado pelo$ DOS/Rwin e foi$ baixado por um$ ftp mal feito.$%OUT_FIM% %TERMINAL_FIM% </noautolink> Bem a opção =-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 designação original.%BR% Obs: No Unix eu deveria fazer: <noautolink> %TERMINAL_INI% $ tr -d '\015' < ArqDoDOS.txt > /tmp/$$ %TERMINAL_FIM% </noautolink> %ATENCAO_INI% Isto aconteceu porque o =ftp= foi feito do modo binário (ou =image=), isto é, sem a interpretação do texto. Se antes da transmissão do arquivo tivesse sido estipulada a opção =ascii= do =ftp=, isto não teria ocorrido. %ATENCAO_FIM% - Olha, depois desta dica tô começando a gostar deste tal de _Shell_, mas ainda tem muita coisa que não consigo fazer. - Pois é, ainda não te falei quase nada sobre programação 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 são as pessoas que estão “logadas” há mais de um dia no seu servidor? - Claro que não! Para isso seria necessário eu conhecer os comandos condicionais que você ainda não me explicou como funcionam. - Deixa eu tentar mudar um pouco a sua lógica 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: %TERMINAL_INI% $ who%OUT_INI% jneves pts/1 Sep 18 13:40 rtorres pts/0 Sep 20 07:01 rlegaria pts/1 Sep 20 08:19 lcarlos pts/3 Sep 20 10:01%OUT_FIM% %TERMINAL_FIM% E veja também o =date=: %TERMINAL_INI% $ date%OUT_INI% Mon Sep 20 10:47:19 BRT 2004%OUT_FIM% %TERMINAL_FIM% Repare que o mês e o dia estão no mesmo formato em ambos os comandos. %DICA_INI% Algumas vezes um comando tem a saída em português e o outro em inglês. Quando isso ocorrer, você pode usar o seguinte artifício: %TERMINAL_INI% $ date%OUT_INI% Mon Sep 20 10:47:19 BRT 2004%OUT_FIM% $ LANG=pt_BR date%OUT_INI% Seg Set 20 10:47:19 BRT 2004%OUT_FIM% %TERMINAL_FIM% Desta forma passando a saída do comando =date= para português. %DICA_FIM% Ora, se em algum registro do =who= eu não encontrar a data de hoje, é sinal que o cara está "logado" há mais de um dia, já que ele não pode ter se "logado" amanhã... Então vamos guardar o pedaço que importa da data de hoje para procurá-la na saída do =who=: %TERMINAL_INI% $ Data=$(date | cut -c 5-10) %TERMINAL_FIM% Eu usei a construção =$(...)=, para priorizar a execução dos comandos antes de atribuir a sua saída à variável =$Data=. Vamos ver se funcionou: %TERMINAL_INI% $ echo $Data%OUT_INI% Sep 20%OUT_FIM% %TERMINAL_FIM% Beleza! Agora, o que temos que fazer é procurar no comando =who= os registros que não possuem esta data. - Ah! Eu acho que estou entendendo! Você falou em procurar e me ocorreu o comando =grep=, estou certo? - Certíssimo! Só que eu tenho que usar o =grep= com aquela opção que ele só lista os registros nos quais ele *não* encontrou a cadeia. Você se lembra que opção é essa? - Claro, é a opção =-v=... - Isso! Tá ficando bão! Então vamos ver: %TERMINAL_INI% $ who | grep -v "$Data"%OUT_INI% jneves pts/1 Sep 18 13:40%OUT_FIM% %TERMINAL_FIM% - E se eu quisesse mais um pouco de perfumaria eu faria assim: %TERMINAL_INI% $ who | grep -v "$Data" | cut -f1 -d ' '%OUT_INI% jneves%OUT_FIM% %TERMINAL_FIM% - Viu? Não foi necessário usar nenhum comando condicional, até porque o nosso mais usado comando condicional, o famoso =if=, não testa condição, mas sim instruções, como veremos agora. ---++ Comandos Condicionais Veja as linhas de comando a seguir: <noautolink> %TERMINAL_INI% $ ls musicas%OUT_INI% musicas%OUT_FIM% $ echo $?%OUT_INI% 0%OUT_FIM% $ ls ArqInexistente%OUT_INI% ls: ArqInexistente: No such file or directory%OUT_FIM% $ echo $?%OUT_INI% 1%OUT_FIM% $ who | grep jneves%OUT_INI% jneves pts/1 Sep 18 13:40 (10.2.4.144)%OUT_FIM% $ echo $?%OUT_INI% 0%OUT_FIM% $ who | grep juliana%OUT_INI% $ echo $?%OUT_FIM% 1 %TERMINAL_FIM% </noautolink> - O que é esse =$?= faz aí? Começando por cifrão (=$=) parece ser uma variável, certo? - Sim é uma variável que contém o código de retorno da última instrução executada. Posso te garantir que se esta instrução foi bem sucedida, $? terá o valor zero, caso contrário seu valor será diferente de zero. ---+++ O Comando if O que o nosso comando condicional =if= faz é testar a variável =$?=. Então vamos ver a sua sintaxe:%BR% <verbatim> if cmd then cmd1 cmd2 cmdn else cmd3 cmd4 cmdm fi </verbatim> ou seja: caso comando =cmd= tenha sido executado com sucesso, os comandos do bloco do =then= (=cmd1=, =cmd2= e =cmdn=) serão executados, caso contrário, os comandos executados serão os do bloco opcional do =else= (=cmd3=, =cmd4= e =cmdm=), terminando com um =fi=. Vamos ver na prática como isso funciona usando um _scriptizinho_ que serve para incluir usuários no =/etc/passwd=: %TERMINAL_INI% $ cat incusu%OUT_INI% #!/bin/bash # Versão 1 if grep ^$1 /etc/passwd then echo Usuario \'$1\' já existe else if useradd $1 then echo Usuário \'$1\' incluído em /etc/passwd else echo "Problemas no cadastramento. Você é root?" fi fi%OUT_FIM% %TERMINAL_FIM% Repare que o =if= está testando direto o comando =grep= e esta é a sua finalidade. Caso o =if= seja bem sucedido, ou seja, o usuário (cujo nome está em =$1=) foi encontrado em =/etc/passwd=, os comandos do bloco do =then= serão executados (neste exemplo é somente o =echo=) e caso contrário, as instruções do bloco do =else= é que serão executadas, quando um novo =if= testa se o comando =useradd= foi executado a contento, criando o registro do usuário em =/etc/passwd=, ou não quando dará a mensagem de erro.%BR% Vejamos sua execução, primeiramente passando um usuário já cadastrado: %TERMINAL_INI% $ incusu jneves%OUT_INI% jneves:x:54002:1001:Julio Neves:/home/jneves:/bin/bash Usuario 'jneves' ja existe%OUT_FIM% %TERMINAL_FIM% 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 saída do comando =grep=. Para evitar que isso aconteça, devemos desviar a saída desta instrução para =/dev/null=, ficando assim: %TERMINAL_INI% $ cat incusu%OUT_INI% #!/bin/bash # Versão 2 if grep ^$1 /etc/passwd > /dev/null # ou: if grep -q ^$1 /etc/passwd then echo Usuario \'$1\' já existe else if useradd $1 then echo Usuário \'$1\' incluído em /etc/passwd else echo "Problemas no cadastramento. Você é root?" fi fi%OUT_FIM% %TERMINAL_FIM% Agora vamos testá-lo como usuário normal (não _root_): <noautolink> %TERMINAL_INI% $ incusu ZeNinguem%OUT_INI% ./incusu[6]: useradd: not found Problemas no cadastramento. Você é root?%OUT_FIM% %TERMINAL_FIM% </noautolink> Epa, aquele erro não era para acontecer! Para evitar que isso aconteça devemos mandar também a saída de erro (_strerr_, lembra?) do =useradd= para =/dev/null=, ficando na versão final assim: %TERMINAL_INI% $ cat incusu%OUT_INI% #!/bin/bash # Versão 3 if grep ^$1 /etc/passwd > /dev/null then echo Usuario \'$1\' já existe else if useradd $1 2> /dev/null then echo Usuário \'$1\' incluído em /etc/passwd else echo "Problemas no cadastramento. Você é root?" fi fi%OUT_FIM% %TERMINAL_FIM% Depois destas alterações e de fazer um =su –= (me tornar _root_) vejamos o seu comportamento: %TERMINAL_INI% $ incusu botelho%OUT_INI% Usuário 'botelho' incluido em /etc/passwd%OUT_FIM% %TERMINAL_FIM% E novamente: %TERMINAL_INI% $ incusu botelho%OUT_INI% Usuário 'botelho' já existe%OUT_FIM% %TERMINAL_FIM% Lembra que eu falei que ao longo dos nossos papos e chopes os nossos programas iriam se aprimorando? Então vejamos agora como poderíamos melhorar o nosso programa para incluir músicas: %TERMINAL_INI% $ cat musinc%OUT_INI% #!/bin/bash # Cadastra CDs (versao 3) # if grep "^$1$" musicas > /dev/null then echo Este álbum já está cadastrado else echo $1 >> musicas sort musicas -o musicas fi%OUT_FIM% %TERMINAL_FIM% Como você viu, é uma pequena evolução da versão anterior, assim, antes de incluir um registro (que pela versão anterior poderia ser duplicado), testamos se o registro começava (=^=) e terminava (=$=) igual ao parâmetro passado (=$1=). O uso do circunflexo (=^=) no início da cadeia e cifrão (=$=) no fim, são para testar se o parâmetro passado (o álbum e seus dados) são exatamente iguais a algum registro anteriormente cadastrado e não somente igual a um pedaço de algum dos registros.%BR% Vamos executá-lo passando um álbum já cadastrado: %TERMINAL_INI% $ musinc "album 4^Artista7~Musica7:Artista8~Musica8"%OUT_INI% Este álbum já está cadastrado%OUT_FIM% %TERMINAL_FIM% E agora um não cadastrado: %TERMINAL_INI% $ musinc "album 5^Artista9~Musica9:Artista10~Musica10" $ cat musicas%OUT_INI% 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%OUT_FIM% %TERMINAL_FIM% - Como você viu, o programa melhorou um pouquinho, mas ainda não 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 não sei como fazer um =if= para testar condições, ou seja o uso normal do comando. - Cara, para isso existe o comando =test=, ele é que testa condições. 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 próxima vez te explico direitinho o uso do =test= e de diversas outras sintaxes do =if=. - Falou! Acho bom mesmo porque eu também 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 usuário, que será passado como parâmetro esta logado (arghh!) ou não. - Aê Chico, mais dois chopes por favor... Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em _Shell_ que mande um e-mail para a nossa <a href="mailto:contato@clavis.com.br?Subject=Curso de Shell com Julio Neves">gerencia de treinamento</a> para informar-se. Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para <a href="mailto:julioneves@openoffice.org?Subject=Dúvidas Papo de Botequim">mim</a>. Valeu!
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r24
<
r23
<
r22
<
r21
<
r20
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r24 - 01 Aug 2009 - 22:32:17 -
BrSalgado
TWikiBar
Página Inicial
Últimas alterações
Índice
Procurar
Estatísticas de Uso
Aviso de Atualização
Configurações Gerais
Projeto Gráfico
Mapa do Site
Quem Somos
Registre-se
?
Regras de Formatação
Biblioteca Gráfica
?
Carinhas Gráficas
Webs Wiki-SL
Amadeu
Anapolivre
ArquivoLivre
Arte
BahiaSocial
BeaBa
BibliotecaLivre
Blogs
BrasilDigital
BrasilELivre
BSM
Ccsa
CESL
CoberturaWiki
Cooperativas
Curriculo
DarvinMarosin
DiaD
Dinamicoop
Economia
EconomiaSolidaria
EducacaoLivre
Ekaaty
Emacsbr
ENSL
Fatos
Festival3
Festival4
Flisol
Fmpb
Formatos
Foswikibr
FSM2005
GNOMEBR
GTTemario2004
GTWeb
Guialivre
HDC
Incubus
InkscapeBrasil
Jogos
KdeBR
KSP
LGM
LinuxStokDoc
Livros
Main
Mentores
MHHOB
MinuanoDigital
MoradiaECidadania
OlhosDagua
Olimpo
OLPC
OOPTQ
Papers
PCLivre
PentahoBrasil
Pessoas
Portal
Prefeituras
PSLAL
PSLBA
PSLBancarios
PSLBrasil
PSLGO
PSLMA
PSLMG
PSLMIP
PSLMT
PSLMulheres
PSLPI
PubFisl10
PubFisl7
PubFisl8
PubFisl9
QuilomboDoSopapo
RadioSL
RedeMesh
RedePopular
RobotWars
Sandbox
Saudelivre
Scribus
Sementes
Shakya
SLRJ
SoftwareLivreIrece
SoftwareLivreVS
SoLiSC
SuporteLivre
System
Telecentros
TeseSA
TextoLivre
TV
TWikiBar
TWikiPtbr
UNELivre
UNIMIX
VilaTorres
WebNordeste
WTRD2004
Este Menu
?skin=free
English
Español
Português brasileiro
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL?
Send feedback