Aula 12 – Loops ‘while’ e ‘until’
Aula 11 – O loop ‘for’ | Índice | Aula 13 – O menu ‘select’
Seu apoio é muito importante para a criação e a manutenção dos cursos gratuitos do canal debxp:
12.1 – Estruturas de repetição condicional
Na aula sobre o loop for
, nós vimos uma estrutura que executava um bloco de comandos à medida em que percorria sequencialmente cada elemento de uma lista. Mas existem outros dois tipos de loop no Bash que, em vez de percorrer valores, irão testar determinadas condições para decidir se continuam executando um bloco de comandos ou não. São os loops while
e until
.
As palavras while e until significam “enquanto” e “até”, respectivamente. Portanto, fica fácil deduzir que os blocos de comandos desses loops continuarão sendo executados “enquanto” uma condição for verdadeira (while
) ou “até” uma condição tornar-se verdadeira (until
).
12.2 – Sintaxe
Toda sintaxe aplicável ao loop while
também é aplicável ao loop until
, o que muda é apenas a forma como cada um deles reage às condições.
# Lopp while...
while CONDIÇÃO; do
COMANDOS
done
while CONDIÇÃO; do COMANDOS; done
# Loop until...
until CONDIÇÃO; do
COMANDOS
done
until CONDIÇÃO; do COMANDOS; done
Importante! A
CONDIÇÃO
não precisa ser necessariamente um comandotest
. Na
verdade, qualquer expressão que retorne um estado0
(sucesso/verdadeiro) ou1
(erro/falso) pode ser utilizada, inclusive os comandos internostrue
,false
e o comando nulo:
.
12.3 – O loop ‘while’
Como dissemos, o loop while
executa repetidamente um bloco de comandos enquanto uma determinada condição for verdadeira:
n=0
while [[ $n -lt 5 ]]; do
echo $n
((n++))
done
Neste caso, nós definimos o valor inicial de n
fora do bloco de comandos. A cada ciclo nós verificamos se o seu valor ainda é menor do que 5, incrementando o valor original em +1
em seguida. Quando o valor de n
, depois de ser incrementado, passar a ser igual a 5, o teste sairá com status 1
(falso), encerrando o loop. Sendo assim, cada um dos comandos no bloco é executado 5 vezes, resultando nesta saída no terminal:
0
1
2
3
4
Importante! Os comandos sempre serão executados durante os ciclos, e não ao final de todos os ciclos. O que delimita o bloco de comandos é a estrutura
do COMANDOS; done
.
12.4 – O loop ‘until’
O loop until
segue a lógica inversa do loop while
. Para que um ciclo seja executado, o teste tem que sair com status 1
(falso), e o loop será interrompido assim que o teste sair com status 0
(verdadeiro).
Por exemplo, para obter o mesmo resultado do exemplo anterior…
n=0
until [[ $n -eq 5 ]]; do
echo $n
((n++))
done
Repare que, já no início, o teste sairia com status 1
(falso), e esta é a condição lógica que o loop until
espera para liberar a execução do bloco de comandos. À medida em que o valor de n
é incrementado, eventualmente ele será igual a 5
, fazendo com que o teste retorne status 0
(verdadeiro) e os clicos sejam interrompidos.
A saída no terminal seria a mesma:
0
1
2
3
4
12.5 – Loops infinitos
Muitas vezes, existe a necessidade de executar loops indefinidamente, deixando por conta de alguma interferência do usuário ou de um teste no bloco de comandos a sua interrupção. Nesses casos, em vez de uma expressão a ser avaliada, nós utilizamos comandos internos que retornam imediatamente um estado de saída:
Comando | Descrição |
---|---|
true |
Retorna sempre o status 0 (sucesso) |
false |
Retorna sempre o status 1 (erro) |
: |
Comando nulo, não faz nada e sempre retorna 0 (sucesso) |
A interrupção de um loop infinito pode ser feita através de alguma intervenção do usuário, seja através do comando Ctrl+C no terminal, da espera pela entrada de um valor de um comando read
, ou através de instruções que resultem na chamada dos comandos break
ou exit
.
Exemplo 1: loop while
infinito…
while true; do
COMANDOS
done
Ou ainda…
while : ; do
COMANDOS
done
Exemplo 2: loop until
infinito…
until false; do
COMANDOS
done
12.6 – Interrompendo loops infinitos
Não existe uma fórmula definitiva para interromper um loop infinito pelo código, mas nós podemos entender o conceito geral analisando alguns exemplos. Aqui, nós utilizaremos apenas o loop while
, mas, como se trata de um loop infinito, pouco importa se vamos utilizar a lógica until false
ou while true
, pois é o que acontece no bloco de comandos que nos interessa.
Exemplo1: utilizando o comando break
…
n=1
while true; do
[[ $n -lt 5 ]] && echo "Ciclo $n" || break
((n++))
done
Como no primeiro exemplo, nós atribuímos o valor 5
à variável n
. Só que, agora, o teste é feito no bloco de comandos, e não na declaração do while
. Se o valor de n
for maior do que 5
, o teste retornará erro (1
) e o comando break
será executado, interrompendo a execução do loop.
Exemplo 2: controlando o loop com o comando read
…
while true; do
read -p "Digite qualquer coisa ou Q para sair: " str
[[ "$str" = [qQ] ]] && echo Saindo... && break \
|| echo "Você digitou $str"
done
Desta vez, o comando read
irá pausar o ciclo até o usuário entrar com algum texto. O texto digitado será armazenado na variável str
e testado para ver se corresponde ao padrão q
ou Q
. Se isso acontecer, o loop será interrompido. Este é um método muito utilizado na construção de menus, assunto da nossa próxima aula.