Neste artigo mostro uma série de recursos disponíveis para o bash que pouca gente conhece, além de como utilizar os recursos deste programa para implementar soluções novas para o usuário.
Tá, todo mundo sabe que existem centenas de formas de utilizar um for no bash. O legal é que a maneira aritmética dele é bem parecida com a sintaxe em C:
$ for ((i=0;i<10;i++))
> do
> echo $i
> done
Onde temos ((inicialização, condição para continuar, incremento)). Mas isso pode ser expandido de uma forma que você não esperaria.
É possível haver mais de uma inicialização, mais de uma condição de continuação, e mais de um incremento. Pode-se até omitir qualquer um destes! (só tome cuidado com loops infinitos).
$ unset z # garantia que "zerou" a variável
$ read -p "digite: " j
$ for ((i=0; (i<=20) && (j!=5); i++,z--))
do
echo $i
read -p "digite: " j
done
echo z vale = $z
O que esse código faz? Ele lê o valor de j, inicializa i com zero, e enquanto i for menor ou igual a 20 E j for diferente de 5, ele lê j do usuário e incrementa i e decrementa z. No final, exibe o valor de z. Fantárdigo!!!
Funciona assim: as inicializações são separadas por vírgula, a condição para continuar pode ser simples ou não, envolver quantas variáveis ou operações (lógicas ou aritméticas) forem necessárias, e os incrementos são separados com vírgula.
Outra boa sacada do pessoal do bash, para aproxima de outras linguagens é o operador ternário:
$ i=20
$ j=15
$ echo $(( i < j ? 1 : 2 ))
2
O que isso significa? Se i for menor que j, retorna (imprime por causa do echo) 1, senão retorna 2. Neste caso retorna 2, pela primeira operação ser falsa.
Outra sacada legal é uma outra sintaxe do laço for. Todo mundo aprende o for assim:
$ for ((i=0;i<10;i++))
> do
> echo $i
> done
Mas se você gosta de uma sintaxe como a do C, pode substituir do e done por { e }:
$ for ((i=0;i<10;i++))
> {
> echo $i
> }
Ou, numa só linha:
$ for ((i=0;i<10;i++)); { echo $i ;}
Hey! Isso nem parece bash!!! Mas é!
Podemos utilizar também essas comparações nos comandos while e until:
$ until ((i==10)); do echo 'Só vou sair se você digitar 10!!!'; read i; done
$ while ((i==10)); do echo 'Não saio enquanto você digitar 10!!!!'; read i; done
É importante notar que já que é possível utilizar variáveis tanto na forma i quanto $i, é possível utilizar saídas de comandos como operandos das operações:
$ if (( $(date +%Y) > 2000 ))
> then
> echo 'Você já está no século XXI!!!!!'
> else
> echo 'Você é antigo, hein...'
> fi
Temos também uma segunda forma de representar saídas de operações aritméticas, em vez de $(( )), que é $[ ]. Exemplo:
$ echo "O ano que vem será $[ $(date +%Y) +1 ] "
2008
[2] Comentário enviado por elgio em 13/09/2007 - 08:49h
Ótimo artigo. Bem oportuno.
Só não entendi direito isto:
"Novamente, o problema da execução de mais de uma operação."
Não entendi este teu problema, que tu citou com AND e OR juntos. Porque mais de uma operação? E o que ocorreu com o 'Short-circuit", técnica do C que também vale para o bash?
Short-circuit: executa só o que é necessário.
Exemplo:
if (( i == 20 )) || (( i > 100 ))
Se o i FOR 20, por causa do OU, simplesmente ele não vai fazer a comparação i>100, pois é desnecessária! Isto pode ser facilmente demonstrado em:
a)
a=20;(( a > 15 )) && (( a=0 )); echo $a
Como a foi maior que 15, "necessitou" realizar o teste no AND e o a recebeu 0.
b)
a=10;(( a > 15 )) && (( a=0 )); echo $a
Como o a NAO FOI maior que 15 (FALSO) não tem porque testar o braço do AND, pois já se sabe que toda a sentença é falsa. Logo o a permanece com 10. Isto é o short-circuit em ação!
A propósito: grandes, enormes, VIOLENTAS perdas de desempenho o pessoal acaba tendo por usar em demasia comandos externos.
[4] Comentário enviado por Gandalfree em 13/09/2007 - 09:02h
Parabéns pelo excelente artigo, não tinha a mínima noção que fosse possível utilizar a sintaxe desta forma. Já estou até maquinando na cabeça mudar meus scripts para ficarem mais fáceis de entender por outros administradores pela familiaridade com C/C++.
[6] Comentário enviado por tenchi em 13/09/2007 - 10:38h
Wow....
Algumas correções...
É, elgio, vc está certo... Se o primeiro comando falha o segundo nem é executado... Falha minha. Vou fazer os testes aqui para ver a diferença de desempenho. ;-)
Esqueci de falar porque é interessante especificar a base numérica de um número. Por exemplo
$ ((10==010))
$ echo $?
1
Mas se você especificar a base do segundo - na verdade de qualquer operando - como sendo decimal:
$ ((10==10#010))
$ echo $?
0
Você não tem este problema...
Ou
$ echo $((10#1+2#10+8#10))
11
Especificando a base numérica de cada um dos operadores... È confuso, mas.... ;-)
[8] Comentário enviado por tenchi em 13/09/2007 - 14:00h
ahuahau, opa Elgio...
Sobre o comentário que eu comentei que você fez, foi um num artigo sobre bash, em que você lançou um desafio sobre o comando while.. hauahua
"- Eu te desafio"
E eu não agüentei e peguei logo o meu "treis oitão".. HUAHAUHAUHA
Ah, quando à questão do desempenho dos comandos, eu pensei na seguinte possibilidade: Fora da parte aritmética do bash, cada comparação é um subprocesso, sendo assim mais lento que somente um processo composto. Mas vejo que não é bem assim. E como ainda não sou jedi suficiente - meu saber ainda dá umas piscadas ;-) - não tenho condições de analizar o código do bash para ver o funcionamento dele.
Ah, já estou lendo o seu artigo comparativo entre o desempenhos das linguagens...
Sobre as apostilas, eu já imediatamente peguei este pdf aí, que já havia visto no blog do Tiago Peczenyj, citado no comentário acima. Livrinho baum hein? Ainda bem que já tô me acostumando a ler livros técnicos em inglês (acredite, eu sou obrigado a aprender isto rsrs).
[11] Comentário enviado por tenchi em 13/09/2007 - 17:34h
Ah, antes que me corrijam... As operações citadas aqui são para valores inteiros... O bash não é capaz de lidar com valores reais, "pontos flutuantes". Para isso utilizem a calculadora bc.
[13] Comentário enviado por capitainkurn em 14/09/2007 - 11:09h
Excelente artigo!!!!!!
Também sou aficionado de programação e Shell script e a cada dia me deparo com mais recursos desconhecidos destes espetaculares interpretadores, especialmente o Bash.
Muito obrigado por enriquecer-nos mais com seu artigo!!!
[19] Comentário enviado por GilsonDeElt em 11/06/2008 - 14:38h
Valeu, Leandro!
ficou d+ seu artigo
Achei ele enquanto procurava saber se era possível trabalhar com binário no bash (afinal, eletrônicos também trabalham com 0s e 1s =D)
E agora, para facilitar meu trabalho (e o de quem lê meus scripts), posso fazer meus bash-scripts quase como um programa C++
(já que tbm tô aprendendo C++, isso vai facilitar meu trabalho ;-)
Eu e os demais scripteiros de plantão e programadores do Bourne Again Shell agradecemos pelo artigo!
té+!
[20] Comentário enviado por wagnerfs em 29/06/2015 - 23:46h
Excelente artigo. Parabéns!
_________________________
Wagner F. de Souza
Técnico/Instrutor de Informática
"GNU/Linux for human beings."
LPI ID: LPI000297782