Curso de Shell - Aula IV
postado por nightnux - comentários
0
Por: Alex Borro
Nesta aula vamos aprender sobre comandos de laço como o while, for, case e select. Eles nos permitem executar alguns comandos diversas vezes, sob determinadas condições e até montar menuzinhos para interagir com o usuário.
While
Este é provavelmente o comando de laço mais utilizado em programação. Seu entendimento é simples. Ele testa uma condição (como faz o IF) e executa um conjunto de comandos se esta condição for verdadeira. Após a execução desses comandos, ele torna a testar a condição e se esta for verdadeira, ele reexecuta os comandos e assim por diante.
Sua sintaxe é a seguinte:
while [ condição ]; do comando 1; comando 2; ... done;
O parâmetro [ condição ] funciona exatamente igual ao do IF. Não voltarei a abortar os parâmetros condicionais pois eles já foram explicados na aula 3. Em caso de dúvida sobre isso, uma rápida revisão na aula 3 é suficiente.
Bom, vamos ao exemplo mais simples do While: um contador.
x = 0 While [ "$x" -le 10 ]; do echo "Execução número: $x"?; x = $((x+1)); done;
Analisando:
Na primeira linha temos a condição: enquanto o valor da variável x ( $x ) for menor-igual ( -le ) a 10, faça: mostre "Execução número: " e o valor de x ($x). Faça x = x + 1. Isso no bash é feito pelo comando $(( )). Ele realiza operações algébricas com variáveis. No caso acima, estamos somando x + 1 e colocando o resultado no próprio x.
Preste atenção, que as linhas do While precisam de um ";" para terminar, exceto a que contém o "do", pois ele representa o começo do bloco de comandos.
Quando executamos o script acima, temos uma contagem de 1 até 10:
neo@matrix:~$ x=0; while [ "$x" -lt 10 ]; do x=$((x+1)); echo "Execução número: $x"; done; Execução número: 1 Execução número: 2 ... Execução número: 10 neo@matrix:~$
O While tem muita utilidade em programação, mas fica difícil dar exemplos usando somente ele, pois geralmente ele está associado a execução de outros programas e rotinas mais complexas.
Eu costumo usar ele, por exemplo, quando quero que o napster fique tentando conectar, pois quando ele vai tentar conectar o servidor e não consegue, ele simplesmente termina. Ai eu coloco o while testando a código de retorno dele (lembram da variável $? ) e enquanto estiver diferente de zero (o napster terminou com erro), ele fica executando o napster:
? = 1; while [ "$?" -ne "0" ]; do ./nap; done;
O comando "? = 1" tenta atribuir 1 a variável ?. Isso provoca um erro, pois a variável ? É somente de leitura. Isso é necessário para que ? Contenha algo diferente de 0, pois senão o While não executa a primeira interação.
For
O for é semelhante ao while usado como um contador. É necessário fornecer uma lista de nomes e ele executa os comandos para cada nome na lista. Parece meio confuso, mas é simples. Veja a sintaxe:
for in ; do comandos done;
O For associa o primeiro item da lista de nomes à variável e executa os comandos. Em seguida, associa novamente o segundo item da lista à e executa novamente os comandos... e assim por diante, até acabar a lista.
Veja o exemplo:
neo@matrix:~$ for x in Compra Venda Aluguel; do echo $x; done; Compra Venda Aluguel
Ou seja, primeiro ele coloca "Compra" na variável x e executa os comandos, no caso, "echo $x", e assim por diante.
Podemos facilmente implementar um contador, usando em conjunto com o for, o programinha "seq". Ele simplesmente gera uma seqüência de números. Por exemplo, "seq 10" gera uma seqüência de 1 até 10. Assim, podemos usá-lo no for:
for x in $(seq 10); do echo $x; done;
Esse comando é semelhante ao contador implementado com o While. Primeiro o x vale 1 e o for executa os comandos. Depois x vale 2 e ele reexecuta os comandos...
Vamos usar o For para renomear os arquivo de um diretório, mudando todos os arquivo terminados em ".mp3" para ".mp3.bak".
for x in *; do mv "$x" "${x}.bak"; done;
for x in *.mp3; do if [ -e "$x" ]; then mv "$x" "${x}.bak"; fi; done;
No local de nos colocamos "*.mp3". Isso diz ao bash para expandir (transformar) ele na lista de arquivos terminados com ".mp3". Senão houver nenhum arquivo com essa terminação, o bash não faz nada, ficando para o for a string "*.mp3". Por isso precisamos do IF para testar se o arquivo existe.
Experimente no seu sistema.
echo *.mp3
Vai mostrar os arquivos no diretório atual com terminação mp3, mas sem quebra de linha entre eles, ou seja, um nome após o outro. Se não houver nenhum arquivo com terminação mp3, ele apenas vai mostrar "*.mp3".
Bom, voltando ao For, ele vai atribuir a "x" cada nome na lista de arquivos com terminação ".mp3" e executar os comandos seguintes.
Primeiro ele testa para ver se o arquivo existe ( if [ -e "$x" ]; ), e se existir, renomeia ele para o seu próprio nome acrescido de ".bak" ( ${x}.bak ).
Resumindo, o For faz isso: você fornece uma lista de nomes para ele e ele vai atribuindo esses nomes, em ordem e um por vez, à variável e executa os comandos entre o "do" e o "done;".
Case
O Case está mais para um comando condicional do que para comando de laço, visto que ele não executa "loopings" como o While e o For.
Ele geralmente é utilizado como substituição de vários IFs.. Um exemplo clássico e muito utilizado é quando você precisa testar um parâmetro fornecido na linha de comando. O Case é utilizado desta forma em scripts de inicialização de serviços do sistema.
Vou mostrar a sintaxe em em seguida um script que inicialize/ reinicialize ou pare algum serviço (como o sendmail, apache, bind, etc).
Sintaxe:
case in
) ;;
[opção 2] ) ;; * ) < comandos se não for nenhuma das opções > ;; esac
Vamos as explicações. O Case pega a string fornecida em e compara com . Se forem iguais, ele executa e sai fora. Caso contrario, ele compara com e assim por diante.
Caso não seja igual a nenhuma das opções, ele executa os comandos da opção "*", se este existir.
Prestem atenção a alguns detalhes na sintaxe. Deve existir um ")" após cada opção e também um ";;" após todos os comandos de cada opção. Vejam o exemplo abaixo:
case "$1" in
'start' ) echo "Iniciando o serviço..." ;; 'restart' ) echo "Reinicializando o serviço..." ;; 'stop' ) echo "Parando o serviço..." ;; *) echo "Opção invalida!" echo "As opções válidas são: start, stop e restart" ;; esac
O Case serve exatamente para isso, ou seja, evitar o teste de vários Ifs. No caso acima, teríamos que utilizar 3 Ifs. Mesmo se o primeiro já fosse verdadeiro, o bash iria testar o segundo e o terceiro, ou seja, ia perder tempo desnecessariamente. Já no case isso não acontece. Após entrar em uma opção e executar seus comandos, ele já pula fora do case sem testar as outras opções abaixo.
Select
O Select é um comando de laço que nos permite mostrar um pequeno menuzinho de opções para o usuário. Cada opção possui um número e para escolher, o usuário digita o número correspondente a opção desejada. Vejamos a sintaxe a seguir:
select in ; do done;
Como disse acima, o select vai mostrar as opções contidas em , uma por linha, com um número na frente e espera que o usuário digite a opção desejada. Ao digitar a opção, o select atribui o nome da opção a variável e executa os comandos. Para sair do select, é necessário executar o comando "break". Vamos a um exemplo:
select x in Iniciar Reiniciar Parar Sair; do echo "Opção Escolhida: $x" if [ "$x" == "Sair" ]; then break; fi; done;
Ou seja, se o usuário escolher alguma opção diferente de "Sair", o script apenas escreve a opção. Se for escolhida Sair, ele mostra a opção, entra no IF e executa o break, saindo do select.
É interessante combinar o Select com o Case. Vamos mostrar como ficaria aquele exemplo do case, de iniciar um serviço, utilizando o Select, para tornar o script interativo:
select x in Iniciar Reiniciar Parar Sair; do
case "$x" in 'Iniciar' ) echo " Iniciando o serviço..." ;; 'Reiniciar' ) echo " Reinicializando o serviço..." ;; 'Parar' ) echo " Parando o serviço..." ;; 'Sair' ) echo " Script encerrado." break ;; *) echo " Opção inválida!" ;; esac done;
Primeiramente o Select mostra um menuzinho:
1) Iniciar 2) Reiniciar 3) Parar 4) Sair #?
Quando o usuário digitar um número de opção, o select executa o case e este compara a variável x com suas opções. Se achar alguma, executa seus comandos, no caso um echo. Se o usuário escolher Sair, além do echo, ele executa o "break", que interrompe o select:
neo@matrix:~/test$ ./t 1) Iniciar 2) Reiniciar 3) Parar 4) Sair #? 1 Iniciando o serviço... 1) Iniciar 2) Reiniciar 3) Parar 4) Sair #? 5 Opção inválida! 1) Iniciar 2) Reiniciar 3) Parar 4) Sair #? 4 Script encerrado. neo@matrix:~/test$
Bom pessoal, acho que por hoje é só. ;-) Espero que vocês tenham pego a idéia de como funciona comandos de laços. Pelos menos sabendo a utilidade, sintaxe e como funcionam, quando surgir a necessidade, vocês já vão saber quais ferramentas usar.
Qualquer dúvida, sugestão, etc, podem me enviar um e-mail. Terei o maior prazer em responder. Até a próxima aula!
|