Programação Shell LinuxAqui temos um livro livre e completo sobre ShellOs sedentos do "saber livre" são muito benvindos. | 
				Comandos Shell Script | 
				![]()  | 
				|
Home |
Artigos     | Agradecimentos
|
Links Amigos
				 | 
				Comprar o livroChangelogs | 
			||
					 | 
		
Papo de Botequim - Parte III- Garçon, traga dois chopes por favor que hoje eu vou ter que falar muito. Trabalhando com cadeiasPelo 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)
Primeiro quero te mostrar, de forma eminentemente prática uma instrução simples de usar e muito útil: o comando   O comando 
 | 
	||||||||||||||||||||||||||||||||
| Principais Opções do comando tr | |
|---|---|
| -d | Remove os caracteres de cadeia1 | 
| Opção | Significado | 
| -s | Comprime n ocorrências de cadeia1 em apenas uma | 
tr Primeiro vou te dar um exemplo bem bobo:
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:
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:
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:
| Escape Sequences | ||
|---|---|---|
| \\ | Uma barra invertida | \0134 | 
| Seqüência | Significado | Octal | 
| \t | Tabulação | \011 | 
| \n |    Nova linha  | 
			\012 | 
| \v | Tabulação Vertical | \013 | 
| \f | Nova Página | \014 | 
| \r | Início da linha <^M> | \015 | 
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:
Eu executava o programa e ele funcionava:
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:
O cara ficou muito desapontado, porque em 2 ou 3 segundos eu desfiz a gozação que ele perdera horas para fazer.
 
Mas preste atenção! Se eu estivesse em uma máquina com Unix, eu teria feito:
tr 
Agora veja a diferença entre os dois comandos date: o que fiz hoje e outro que foi executado há duas semanas:
Para pegar a hora eu deveria fazer:
Mas duas semanas antes ocorreria o seguinte:
Mas observe porque:
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:
Como você pode ver não existem mais os dois espaços, então agora eu poderia cortar:
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:
E agora eu quero te dar duas dicas:
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 #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. 
Vamos então limpar este arquivo.
Agora vamos ver o que aconteceu:
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.
Obs: No Unix eu deveria fazer:
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.
- 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:
E veja também o date:
Repare que o mês e o dia estão no mesmo formato em ambos os comandos.
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:
date para português.
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:
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:
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:
- E se eu quisesse mais um pouco de perfumaria eu faria assim:
- 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.
Veja as linhas de comando a seguir:
- 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 que o nosso comando condicional if faz é testar a variável $?. Então 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) 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:
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.
 
Vejamos sua execução, primeiramente passando um usuário já cadastrado:
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:
Agora vamos testá-lo como usuário normal (não root):
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:
Depois destas alterações e de fazer um su – (me tornar root) vejamos o seu comportamento:
E novamente:
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:
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.
Vamos executá-lo passando um álbum já cadastrado:
E agora um não cadastrado:
- 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 gerencia de treinamento para informar-se.
Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para mim.
Valeu!