Linux - Laços
Os laços permitem executar um conjunto de comandos repetidamente, dependendo de uma condição. Bash oferece os seguintes tipos de laços:
- for: executa um determinado número de vezes
- while: executa enquanto a condição especificada for verdadeira
- until: executa até que a condição especificada se torne verdadeira
Laço while
O laço while executa enquanto uma condição for verdadeira e tem a seguinte sintaxe:
while condição
do
    comandos_a_serem_executados
doneApós o while, vem a condição que será avaliada. Enquanto essa condição for verdadeira, o conjunto de comandos entre os operadores do e done será executado. Vamos considerar um exemplo simples:
#!/bin/bash
# Script que utiliza o laço while
num=0
while [ $num -lt 5 ]
do
    echo "num é igual a $num"
    num=$((num+1))
done
echo "Fim do programa"
exit 0Aqui, a condição é a seguinte expressão: [ $num -lt 5 ]. Ou seja, a condição é verdadeira enquanto a variável num for menor que 5 (por padrão, ela começa com valor 0). E enquanto essa condição for verdadeira, dois comandos são executados:
echo "num é igual a $num" num=$((num+1))
Isso significa que o valor da variável num é exibido no console e seu valor é incrementado em 1. Dessa forma, o laço será executado 5 vezes. Ao executar o script:
programicio@Programicio:~$ bash hello num é igual a 0 num é igual a 1 num é igual a 2 num é igual a 3 num é igual a 4 Fim do programa
Laço until
O laço until é semelhante ao while, mas possui ação inversa: ele executa o laço até que a condição se torne verdadeira. Por exemplo:
#!/bin/bash
# Script que utiliza o laço until
num=0
until [ $num -eq 5 ]
do
    echo "num é igual a $num"
    num=$((num+1))
done
echo "Fim do programa"
exit 0Aqui, os mesmos comandos do laço são usados, mas com uma condição diferente: $num -eq 5, ou seja, verifica se a variável num é igual a 5. Se for igual, o script termina sua execução.
O resultado do script será idêntico ao anterior:
programicio@Programicio:~$ bash hello num é igual a 0 num é igual a 1 num é igual a 2 num é igual a 3 num é igual a 4 Fim do programa
Laço for
O laço for executa um conjunto de comandos um determinado número de vezes.
for (( contador; condição; incremento_do_contador)); do
    conjunto_de_comandos
doneApós a palavra for, entre parênteses duplos, temos o cabeçalho do laço, que consiste em três partes separadas por ponto e vírgula. A primeira parte define o contador. A segunda parte é a condição que, enquanto for verdadeira, o laço será executado. A terceira parte é o incremento ou alteração do contador.
Após o cabeçalho do laço, entre as palavras do e done, temos os comandos do laço.
Por exemplo, se precisamos executar uma ação 5 vezes, podemos definir o seguinte script:
#!/bin/bash
# Script que utiliza o laço for
for ((i=0; i < 5; i++))
do
    echo "i é igual a $i"
done
echo "Fim do programa"
exit 0Aqui, o contador é a variável i, que começa com o valor 0.
A condição i < 5 é verdadeira enquanto a variável i for menor que 5.
Após cada execução dos comandos do laço, o valor da variável i é incrementado em 1 (i++).
O corpo do laço é composto por um comando que exibe o valor da variável i no console:
echo "i é igual a $i"
Dessa forma, antes de executar o laço, a variável i é definida como 0. Em seguida, a condição i < 5 é verificada. Se i for menor que 5, o comando echo i é igual a $i é executado. Após a execução, o valor da variável i é incrementado em 1 (i++). Todo o processo se repete: a condição é verificada novamente e os comandos do laço são executados. Se a condição não for verdadeira: i é igual ou maior que 5, o laço termina. Ao executar o script, obteremos o seguinte resultado:
programicio@Programicio:~$ bash hello i é igual a 0 i é igual a 1 i é igual a 2 i é igual a 3 i é igual a 4 Fim do programa
Para definir condições, podemos usar os operadores de comparação padrão: < (menor que), > (maior que), <= (menor ou igual), >= (maior ou igual), == (igual), != (diferente).
Para incrementar o contador do laço, podemos usar operadores de incremento (aumento de 1) ++, decremento (diminuição de 1) --, aumento com atribuição +=, diminuição com atribuição -=. Por exemplo, para aumentar o contador em 2:
for ((i=0; i < 5; i=i+2))
do
    echo "i é igual a $i"
doneOutro exemplo é executar o laço até que o contador se torne igual a 0:
#!/bin/bash
# Script que utiliza o laço for
for ((i=10; i != 0; i--))
do
    echo "i é igual a $i"
done
echo "Fim do programa"
exit 0Laço for..in
Uma forma especial do laço for, o for..in, permite iterar sobre um conjunto de valores:
for variável in conjunto_de_valores
do
    conjunto_de_comandos
doneO laço for passa por um conjunto de valores, colocando cada valor na variável. Entre os comandos do e done são colocados os comandos que serão executados para cada valor do conjunto.
Por exemplo, podemos iterar sobre um arquivo de texto linha por linha:
#!/bin/bash
for i in `cat /etc/passwd`
do
    echo $i
done
exit 0Neste exemplo, todas as linhas do arquivo /etc/passwd são iteradas. Para obter as linhas, usamos o comando cat /etc/passwd, que representa um conjunto de linhas. Cada linha é colocada na variável i. Para cada linha, o comando echo $i é executado.
Outro exemplo seria pingar alguns endereços da rede local. Para isso, definimos o seguinte script:
#!/bin/bash
for i in $@
do
    ping -c 1 192.168.1.$i
done
exit 0Observe o uso de $@. Esse identificador permite acessar todos os argumentos fornecidos ao script na linha de comando, independentemente da quantidade. Usando o laço for, podemos iterar sobre cada um desses argumentos. Vamos executar o script passando um intervalo de endereços:
programicio@Programicio:~$ bash hello 1 2 3 4 5 PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. --- 192.168.1.1 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data. --- 192.168.1.2 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms PING 192.168.1.3 (192.168.1.3) 56(84) bytes of data. --- 192.168.1.3 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms PING 192.168.1.4 (192.168.1.4) 56(84) bytes of data. --- 192.168.1.4 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms PING 192.168.1.5 (192.168.1.5) 56(84) bytes of data. 64 bytes from 192.168.1.5: icmp_seq=1 ttl=62 time=67.8 ms --- 192.168.1.5 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 67.823/67.823/67.823/0.000 ms
Nesse caso, o script recebe o conjunto 1 2 3 4 5, e todo esse conjunto está disponível através de $@. Durante a iteração no laço, cada número do conjunto é colocado na variável i, que é usada para pingar o endereço.