Aritmética
Nesta aula, você aprenderá a realizar operações aritméticas em shell script usando as construções $(( )) e let, além de conhecer os operadores disponíveis. Também verá como usar o bc para cálculos com ponto flutuante.
A aritmética em shell script é uma habilidade essencial para automatizar tarefas que envolvem números, como contagens, cálculos de tempo, processamento de dados numéricos e muito mais. O Bash oferece várias maneiras de realizar operações matemáticas, desde expressões inteiras simples até cálculos com ponto flutuante usando ferramentas externas.
Nesta aula, vamos explorar as principais formas de fazer aritmética no Bash: a expansão aritmética com $(( )), o comando let, os operadores disponíveis e o uso do bc para trabalhar com números decimais. Ao final, você será capaz de incorporar cálculos matemáticos em seus scripts de forma eficiente e precisa.
$(( ))
A expansão aritmética $(( )) é a forma mais comum e recomendada para realizar operações matemáticas inteiras no Bash. Ela avalia uma expressão aritmética e retorna o resultado, que pode ser usado em atribuições, condições ou diretamente em comandos.
A sintaxe é simples: dentro de $(( )), escreva a expressão usando operadores aritméticos padrão. O Bash suporta adição, subtração, multiplicação, divisão inteira, exponenciação e módulo. Exemplo:
#!/bin/bash
# Exemplo básico de $(( ))
resultado=$(( 10 + 5 ))
echo "10 + 5 = $resultado"
# Usando variáveis
a=10
b=3
soma=$(( a + b ))
echo "$a + $b = $soma"
# Divisão inteira (trunca)
div=$(( a / b ))
echo "$a / $b = $div" # Resultado: 3
# Exponenciação
exp=$(( 2 ** 3 ))
echo "2^3 = $exp"
# Módulo
mod=$(( a % b ))
echo "$a % $b = $mod"
A expansão aritmética também suporta operadores de incremento e decremento, e pode ser usada em expressões mais complexas com parênteses para controle de precedência.
let
O comando let é outra forma de realizar aritmética em Bash, mas é menos usado atualmente porque a sintaxe de $(( )) é mais clara e flexível. O let avalia uma expressão e atribui o resultado a uma variável, mas não requer o sinal de dólar para referenciar variáveis dentro da expressão.
Exemplo:
#!/bin/bash
let "a = 10 + 5"
echo "a = $a" # 15
let "b = a * 2"
echo "b = $b" # 30
# Incremento
let "a += 1"
echo "a = $a" # 16
# Decremento
let "b -= 5"
echo "b = $b" # 25
Note que, com let, é necessário usar aspas se a expressão contiver espaços ou operadores especiais. Além disso, let não retorna o resultado diretamente; ele modifica variáveis e retorna um código de saída (0 se a expressão for verdadeira, 1 se for falsa). Por isso, é mais comum usar $(( )) para atribuições simples.
Operadores
O Bash oferece uma variedade de operadores aritméticos para uso em $(( )) e let. Aqui estão os principais:
+(adição)-(subtração)*(multiplicação)/(divisão inteira)%(módulo)**(exponenciação)++(incremento)--(decremento)+=,-=,*=,/=,%=(atribuição composta)
Exemplo de operadores compostos:
#!/bin/bash
x=10
(( x += 5 )) # x = x + 5
echo "x = $x" # 15
(( x *= 2 )) # x = x * 2
echo "x = $x" # 30
(( x-- )) # x = x - 1
echo "x = $x" # 29
Além disso, expressões lógicas e relacionais podem ser usadas em $(( )) para produzir 0 (falso) ou 1 (verdadeiro): <, >, <=, >=, ==, !=, &&, ||, !.
Exemplo:
#!/bin/bash
resultado=$(( 5 > 3 ))
echo "5 > 3 é $resultado" # 1
resultado=$(( 10 == 5 ))
echo "10 == 5 é $resultado" # 0
bc para ponto flutuante
O Bash, por padrão, só trabalha com números inteiros. Para cálculos com ponto flutuante, precisamos usar uma ferramenta externa como o bc (basic calculator). O bc é uma calculadora de precisão arbitrária que suporta operações com decimais e funções matemáticas.
Para usar bc em um script, geralmente passamos a expressão via pipe ou usando here-string. Exemplo:
#!/bin/bash
# Calculando 10 dividido por 3 com duas casas decimais
resultado=$(echo "scale=2; 10 / 3" | bc)
echo "10 / 3 = $resultado" # 3.33
# Usando variáveis
a=5.5
b=2.2
soma=$(echo "$a + $b" | bc)
echo "$a + $b = $soma"
# Funções: seno, cosseno, etc.
pi=$(echo "scale=10; 4*a(1)" | bc -l)
echo "pi = $pi"
O parâmetro scale define o número de casas decimais. A opção -l carrega a biblioteca matemática padrão, que inclui funções como s (seno), c (cosseno), a (arctangente), l (logaritmo natural), e (exponencial), entre outras.
Para expressões mais complexas, podemos usar here-string ou pipe. Exemplo com here-string:
#!/bin/bash
bc <<< "scale=2; (10.5 + 3.2) * 2"
Lembre-se de que bc é um comando externo, então cada chamada gera um subprocesso. Para muitas operações, isso pode ser menos eficiente, mas para a maioria dos scripts é aceitável.
Boas práticas
- Preferir
$(( ))para aritmética inteira, pois é mais legível e eficiente. - Use
letapenas se precisar de compatibilidade com versões muito antigas do Bash. - Para ponto flutuante, utilize
bccomscaleadequado e, se necessário, a biblioteca-l. - Evite usar
expr(comando antigo) – é obsoleto e menos seguro. - Lembre-se de que a divisão inteira trunca para baixo; se precisar de arredondamento, use
bc.
Referências
- GNU Bash Manual - Arithmetic Expansion
- GNU Bash Manual - Conditional Expressions
- GNU bc Manual
- Advanced Bash-Scripting Guide - Arithmetic Expansion
- Bash Hackers Wiki - Arithmetic
- Stack Overflow - Bash Arithmetic Questions
Exercícios
Escreva um script que calcule a média aritmética de três números fornecidos como argumentos na linha de comando. Use $(( )) para inteiros e exiba o resultado.
✓ Resposta:#!/bin/bash # Verifica se foram passados três argumentos if [ $# -ne 3 ]; then echo "Uso: $0 num1 num2 num3" exit 1 fi # Calcula a média (soma / 3) soma=$(( $1 + $2 + $3 )) media=$(( soma / 3 )) echo "Média: $media"Crie um script que use o comando
letpara incrementar uma variável de 0 a 10 em um loopwhilee exiba o valor a cada iteração.✓ Resposta:#!/bin/bash i=0 while [ $i -le 10 ]; do echo "i = $i" let "i += 1" doneEscreva um script que calcule o fatorial de um número inteiro positivo fornecido como argumento. Use $(( )) para a aritmética.
✓ Resposta:#!/bin/bash if [ $# -ne 1 ] || [ $1 -lt 0 ]; then echo "Uso: $0 numero_positivo" exit 1 fi num=$1 fatorial=1 while [ $num -gt 1 ]; do fatorial=$(( fatorial * num )) num=$(( num - 1 )) done echo "Fatorial de $1 é $fatorial"Use
bcpara calcular a área de um círculo com raio fornecido como argumento (use pi com 10 casas decimais). Exiba o resultado com 2 casas decimais.✓ Resposta:#!/bin/bash if [ $# -ne 1 ]; then echo "Uso: $0 raio" exit 1 fi raio=$1 area=$(echo "scale=2; 4*a(1) * $raio^2" | bc -l) echo "Área do círculo com raio $raio: $area"Crie um script que receba dois números e um operador (+, -, *, /, %) e realize a operação usando $(( )) para inteiros. Se a operação for divisão e o divisor for zero, exiba uma mensagem de erro.
✓ Resposta:#!/bin/bash if [ $# -ne 3 ]; then echo "Uso: $0 num1 operador num2" echo "Operadores: +, -, *, /, %" exit 1 fi num1=$1 op=$2 num2=$3 case $op in +) resultado=$(( num1 + num2 )) ;; -) resultado=$(( num1 - num2 )) ;; \*) resultado=$(( num1 * num2 )) ;; /) if [ $num2 -eq 0 ]; then echo "Erro: divisão por zero!" exit 1 fi resultado=$(( num1 / num2 )) ;; %) if [ $num2 -eq 0 ]; then echo "Erro: módulo por zero!" exit 1 fi resultado=$(( num1 % num2 )) ;; *) echo "Operador inválido: $op" exit 1 ;; esac echo "$num1 $op $num2 = $resultado"