Os laços while e until são estruturas de repetição fundamentais em Shell Script. Enquanto while executa um bloco de comandos enquanto uma condição for verdadeira, until executa até que a condição se torne verdadeira (ou seja, enquanto for falsa). Ambos são amplamente usados para processamento de arquivos, validação de entrada, e loops com contagem variável. Nesta aula, exploraremos a sintaxe, exemplos práticos e técnicas como o uso de read para ler arquivos e os comandos break e continue para controle fino dos loops.

while

O laço while executa uma lista de comandos repetidamente enquanto uma condição for verdadeira (código de retorno 0). A sintaxe básica é:

while condição
do
    comandos
done

A condição pode ser qualquer comando ou teste (por exemplo, test ou [ ]). O loop termina quando o comando da condição retorna um código diferente de zero (falso). Exemplo simples:

#!/bin/bash
contador=1
while [ $contador -le 5 ]
do
    echo "Contagem: $contador"
    ((contador++))
done

Neste exemplo, o loop imprime os números de 1 a 5. A condição [ $contador -le 5 ] é verdadeira enquanto a variável contador for menor ou igual a 5. Dentro do loop, incrementamos a variável com ((contador++)).

until

O laço until é semelhante ao while, mas executa enquanto a condição for falsa (código de retorno diferente de zero). A sintaxe é:

until condição
do
    comandos
done

O loop termina quando a condição se torna verdadeira. Exemplo equivalente ao anterior, mas usando until:

#!/bin/bash
contador=1
until [ $contador -gt 5 ]
do
    echo "Contagem: $contador"
    ((contador++))
done

Aqui, a condição [ $contador -gt 5 ] é falsa enquanto contador for menor ou igual a 5. Quando contador se torna 6, a condição se torna verdadeira e o loop termina.

read em while (lendo arquivos)

Uma aplicação muito comum do while é ler arquivos linha por linha usando o comando read. O comando read lê uma linha da entrada padrão (ou de um arquivo redirecionado) e atribui os campos a variáveis. A estrutura típica é:

while IFS= read -r linha
do
    echo "Linha: $linha"
done < "arquivo.txt"

Explicação: IFS= evita que espaços em branco no início/fim da linha sejam removidos; -r impede que barras invertidas sejam interpretadas como escapes. O redirecionamento < "arquivo.txt" fornece o conteúdo do arquivo como entrada para o while. Exemplo prático:

#!/bin/bash
while IFS= read -r linha
do
    echo "Processando: $linha"
done < /etc/passwd

Este script lê o arquivo /etc/passwd e imprime cada linha com o prefixo "Processando:".

break e continue

Os comandos break e continue permitem controlar o fluxo dentro de loops. break sai do loop imediatamente, enquanto continue pula para a próxima iteração (ignorando os comandos restantes no corpo do loop). Exemplo com break:

#!/bin/bash
for num in 1 2 3 4 5
do
    if [ $num -eq 3 ]; then
        echo "Encontrou 3, saindo..."
        break
    fi
    echo "Número: $num"
done

Saída: Número: 1, Número: 2, Encontrou 3, saindo...

Exemplo com continue:

#!/bin/bash
for num in 1 2 3 4 5
do
    if [ $num -eq 3 ]; then
        echo "Pulando o 3..."
        continue
    fi
    echo "Número: $num"
done

Saída: Número: 1, Número: 2, Pulando o 3..., Número: 4, Número: 5.

Ambos podem ser usados com um argumento numérico opcional para sair/pular de loops aninhados. Por exemplo, break 2 sai de dois níveis de loops.

Boas práticas

  • Sempre use IFS= read -r ao ler arquivos para preservar espaços e barras invertidas.
  • Evite loops infinitos acidentais: certifique-se de que a condição do while ou until se tornará falsa em algum momento.
  • Prefira while para loops baseados em condição e until quando a lógica for "até que algo aconteça".
  • Use break e continue com moderação para manter a legibilidade.

Referências

Exercícios

  1. Crie um script que use um loop while para imprimir os números de 10 a 1 (ordem decrescente).
  2. ✓ Resposta:
    #!/bin/bash
    contador=10
    while [ $contador -ge 1 ]
    do
        echo $contador
        ((contador--))
    done
  3. Escreva um script usando until que leia números do usuário até que ele digite "fim".
  4. ✓ Resposta:
    #!/bin/bash
    entrada=""
    until [ "$entrada" = "fim" ]
    do
        read -p "Digite um número (ou 'fim' para sair): " entrada
        if [ "$entrada" != "fim" ]; then
            echo "Você digitou: $entrada"
        fi
    done
  5. Use um loop while com read para exibir apenas as linhas ímpares de um arquivo (por exemplo, /etc/hosts). Dica: use um contador.
  6. ✓ Resposta:
    #!/bin/bash
    linha_num=1
    while IFS= read -r linha
    do
        if ((linha_num % 2 == 1)); then
            echo "$linha_num: $linha"
        fi
        ((linha_num++))
    done < /etc/hosts
  7. Crie um script que use while e break para encontrar o primeiro número divisível por 7 entre 1 e 50.
  8. ✓ Resposta:
    #!/bin/bash
    num=1
    while [ $num -le 50 ]
    do
        if ((num % 7 == 0)); then
            echo "Primeiro número divisível por 7: $num"
            break
        fi
        ((num++))
    done
  9. Escreva um script que, usando while e continue, imprima apenas os números pares de 1 a 20.
  10. ✓ Resposta:
    #!/bin/bash
    num=1
    while [ $num -le 20 ]
    do
        if ((num % 2 != 0)); then
            ((num++))
            continue
        fi
        echo $num
        ((num++))
    done