De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Rodrigo Bernardo Pimentel
Data de Publicação: 16 de Agosto de 2000
É comum queremos executar a mesma função, ou uma função parecida, sobre uma série de argumentos, um por vez.
Em bash, há duas estruturas básicas pra isso: for
e while
.
O for
, em bash, é diferente do for
em linguagens como C ou
Perl. Nessas linguagens, o for
é simplesmente um while
mais completo. Em
bash, o for
atua sobre uma seqüência de parâmetros (não necessariamente
numéricos ou seqüenciais). Por exemplo:
[rbp@muppets ~]$ for i in 1 2 3 4 5; do echo $i; done
1
2
3
4
5
Ou,
[root@muppets ~]$ for login in rbp sizinha queiroz; do adduser $login; done [root@muppets ~]$
Você pode inclusive usar o for
a partir de uma saída de comando. Por
exemplo, digamos que você tenha um arquivo com uma série de nomes de
usuários a serem acrescentados ao sistema, como no exemplo acima:
[root@muppets ~]$ for login in $(O
while
, por sua vez, tem funcionamento semelhante à maioria das linguagens procedurais mais comuns. Um comando ou bloco de comandos continua a ser executado enquanto uma determinada condição for verdadeira. Por exemplo, imitando o exemplo acima:[rbp@muppets ~]$ while [ $i -le 5 ]; do echo $i; i=$(($i + 1)); done 1 2 3 4 5
Aos poucos:
while [ $i -le 5 ]O
while
deve ser seguido deverdadeiro
oufalso
. Se forverdadeiro
, o bloco é executado e o teste é repetido. Se forfalso
, não.No caso,
[ $i -le 5 ]
é uma forma de usarmos o comandotest
. Esse comando testa uma expressão e retorna verdadeiro ou falso. Poderia ser escrito comowhile test $i -le 5
$i -le 5
é a expressão testada. O programatest
aceita alguns operadores. Entre eles:
Operador | Significado |
---|---|
-lt (less than) |
primeiro argumento é menor do que o segundo |
-le (less or equal) |
primeiro argumento é menor ou igual ao segundo |
-gt (greater than) |
primeiro argumento é maior do que o segundo |
-ge (greater or equal) |
primeiro argumento é maior ou igual ao segundo |
= |
primeiro argumento é igual ao segundo |
!= |
primeiro argumento é diferente do segundo |
O programa test
pode também fazer testes unários
, ou seja, com
só um argumento. Por exemplo,
arq="/tmp/arquivo" tmp=$arq i=1 while [ -e $tmp ]; do i=$(($i+1)) tmp=$arq$i done touch $tmp
Esse scriptzinho (note que não o fiz na linha de comando, mas indentado, para
usá-lo a partir de um arquivo; funciona dos dois jeitos) só sai do loop
quando achar um nome de arquivo que não exista. Ou, de forma mais didática,
"enquanto existir (-e
) o arquivo cujo nome está na variável $tmp
,
ele continua executado o bloco de comandos".
Alguns dos operadores unários mais comuns são:
Operador | Significado |
---|---|
-e |
arquivo ou diretório existe |
-f |
é um arquivo (em oposição a ser um diretório) |
-d |
é um diretório |
-x |
arquivo tem permissão de execução para o usuário atual |
-w |
arquivo tem permissão de escrita pelo usuário atual |
-r |
arquivo tem permissão de leitura pelo usuário atual |
Para mais detalhes, man test
.
Continuando:
do echo $i
Logo após um while <teste>
, é preciso iniciar o primeiro comando
com do
. Os seguintes (se houver), não.
A próxima linha mostra um exemplo de algo que não tem nada a ver com
a estrutura do while
em si, mas é um truquezinho legal de bash:
i=$(($i + 1))
A construção $((expressão))
é um operador matemático em bash. Isso
é expandido para o resultado da expressão. Por exemplo,
[rbp@muppets ~]$ echo $((2 + 3)) 5 [rbp@muppets ~]$ echo $((2 - 3)) # Funciona com números negativos= -1 [rbp@muppets ~]$ echo $((2 * 3)) 6 [rbp@muppets ~]$ echo $((10 / 2)) 5 [rbp@muppets ~]$ echo $((3 / 2)) # Não usa casas decimais 1 [rbp@muppets ~]$
Mas, como diz um amigo meu, voltando...
done
Isso termina oficialmente
o loop while
. A propósito, como pode
ter sido notado, termina o for
também.
Como foi dito acima, o while espera verdadeiro
ou falso
. Eu
nunca disse que esperava isso só do programa test
:)
Com efeito, qualquer expressão pode ser usada, e seu valor de
retorno será utilizado para determinar se é verdadeiro
ou falso
. Para
quem não sabe, todo programa em Unix retorna um valor ao terminar sua
execução. Normalmente, se tudo correu bem o valor retornado é 0
(zero). Se
há algum erro, o valor retornado, diferente de zero, indica o tipo de erro
(veja as manpages dos programas; man fetchmail
seção exit codes
é
um bom exemplo). Portanto, ao contrário do que programadores de C ou Perl
poderiam achar intuitivo (dentro de um while
, ou uma condição em geral),
um programa que retorna 0
é considerado verdadeiro
aos olhos do while
.
Assim, podemos fazer:
while w | grep -qs rbp; do sleep 5s done echo 'rbp acaba de sair do sistema!'
Nesse exemplo, o while checa o retorno da expressão w | grep -qs rbp
.
Isso retorna verdadeiro
quando o grep
acha rbp
na saída do comando
w
. Toda vez que achar, espera 5 segundos e checa de novo. Quando não
achar, sai do loop e mostra um aviso de que a última sessão do rbp
foi
fechada.
Pra finalizar: se você quiser fazer um loop infinito, pode usar :
(dois pontos) como condição sempre verdadeira:
while : ; do echo 'Emacs rules!' done
Isso vai imprimir uma constatação sábia infinitamente, até você usar
C-c
(Ctrl + C
). Normalmente, isso é utilizado com alguma condição de
parada. Mas if
fica pra outra dica :)
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários