shell-script-pt
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fwd: [Dicas-L]Bash: Estruturas Básicas


From: Mauricio Bonani
Subject: Fwd: [Dicas-L]Bash: Estruturas Básicas
Date: Thu, 17 Aug 2000 00:56:32 -0300


>From mail Wed Aug 16 00:52:54 2000
>From address@hidden  Wed Aug 16 00:52:54 2000
To: address@hidden
Subject: [Dicas-L]Bash: Estruturas Básicas
Date: Wed, 16 Aug 2000 00:22:57 -0300 (EST)
From: address@hidden (Rubens Queiroz de Almeida #200503# )

Bash: Estruturas Básicas
---------------------------------------------------------------------
Colaboração: Rodrigo Bernardo Pimentel <address@hidden>

É 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
[rbp@muppets ~]$

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 `cat /tmp/usuarios`; do adduser $login; done
[root@muppets ~]$

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
[rbp@muppets ~]$

Aos poucos:

while [ $i -le 5 ]

O "while" deve ser seguido de "verdadeiro" ou "falso". Se for
"verdadeiro", o bloco é executado e o teste é repetido. Se for falso, não.

No caso, "[ $i -le 5 ]" é uma forma de usarmos o comando
"test". Esse comando testa uma expressão e retorna verdadeiro ou
falso. Poderia ser escrito como

while test $i -le 5

"$i -le 5" é a expressão testada. O programa "test" aceita alguns
operadores. Entre eles:

-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:

-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 :)
---------------------------------------------------------------
As mensagens da lista Dicas-L são veiculadas diariamente
para 9603 assinantes.

Para sair ou assinar a lista Dicas-L, consulte o documento que
se encontra em http://www.Dicas-L.unicamp.br/FAQ.html.

A redistribuição desta e outras mensagens da lista Dicas-L pode
ser feita livremente, deste que o conteúdo, inclusive esta nota,
não sejam modificados.
---------------------------------------------------------------


--
Mauricio Bonani
mailto:address@hidden
ICQ UIN: 2743356
Registered Linux User #131602
Using Red Hat 6.2
São Paulo - SP



reply via email to

[Prev in Thread] Current Thread [Next in Thread]