Aritmética
Esta aula aborda como realizar operações aritméticas em shell script, cobrindo desde expressões inteiras com $(( )) e let, operadores comuns, até cálculos com ponto flutuante usando bc.
A aritmética é uma necessidade frequente em scripts de shell, seja para contar iterações, calcular totais ou processar dados numéricos. O Bash oferece suporte nativo a operações com números inteiros, mas para ponto flutuante é necessário recorrer a ferramentas externas como o bc. Nesta aula, exploraremos as principais formas de realizar cálculos em shell script, com exemplos práticos e boas práticas.
$(( ))
A forma mais comum e recomendada para aritmética inteira em Bash é a expansão aritmética $(( expressão )). Ela avalia a expressão, substitui pelo resultado e pode ser usada em atribuições, testes condicionais e argumentos de comandos.
Exemplo básico:
#!/bin/bash
a=$((5 + 3))
echo $a # 8
b=$((a * 2))
echo $b # 16
Você pode usar variáveis diretamente, sem o cifrão, dentro de $(( )):
x=10
y=20
soma=$((x + y))
echo $soma # 30
Expressões podem ser combinadas com operadores de comparação, retornando 1 para verdadeiro e 0 para falso:
echo $((5 > 3)) # 1
echo $((5 == 3)) # 0
let
O comando let é outra forma de realizar aritmética inteira, mas é menos flexível e mais antigo. Ele avalia uma expressão e atribui o resultado a uma variável, sem a necessidade de $ ou parênteses.
Exemplo:
let a=5+3
echo $a # 8
let b=a*2
echo $b # 16
Também permite operadores de atribuição combinada:
let a+=2 # equivalente a a = a + 2
echo $a # 10
No entanto, let não é tão seguro quanto $(( )) e pode ter problemas com espaços e caracteres especiais. A recomendação moderna é preferir $(( )).
Operadores
Os operadores aritméticos disponíveis em Bash incluem:
+(adição)-(subtração)*(multiplicação)/(divisão inteira)%(módulo)**(exponenciação)++e--(incremento/decremento)
Exemplos:
echo $((10 / 3)) # 3 (divisão inteira)
echo $((10 % 3)) # 1
echo $((2 ** 4)) # 16
Também é possível usar operadores de atribuição como +=, -=, *=, etc., dentro de $(( )) e let.
Comparações: <, >, <=, >=, ==, !=. Elas retornam 1 (verdadeiro) ou 0 (falso).
bc para ponto flutuante
O Bash não suporta números de ponto flutuante nativamente. Para cálculos com decimais, usamos o programa externo bc (basic calculator). Ele é um poderoso calculador de precisão arbitrária que pode ser chamado via pipe ou substituição de comando.
Exemplo básico:
echo "scale=2; 10 / 3" | bc # 3.33
A variável scale define o número de casas decimais. Você pode passar expressões mais complexas:
resultado=$(echo "scale=4; (5.5 + 3.2) * 2.1" | bc)
echo $resultado # 18.27
Para atribuir a uma variável, use substituição de comando $():
pi=$(echo "scale=10; 4*a(1)" | bc -l)
echo $pi # 3.1415926532 (com a biblioteca -l)
A opção -l carrega a biblioteca matemática padrão, que inclui funções como s(), c(), a() (arctan), etc.
Exemplo de script que calcula a média de dois números:
#!/bin/bash
n1=7.5
n2=8.3
media=$(echo "scale=2; ($n1 + $n2) / 2" | bc)
echo "Média: $media"
Para maior precisão, você pode usar bc sem scale e definir a precisão dentro da expressão:
echo "scale=5; 1/3" | bc # .33333
Lembre-se de que bc é um comando externo, então seu uso pode ser um pouco mais lento que a aritmética nativa, mas é a solução padrão para ponto flutuante em shell.
Boas práticas
- Prefira
$(( ))para aritmética inteira, evitandoleteexpr(obsoleto). - Use
bccomscaleadequado para cálculos decimais. - Evite aritmética dentro de
[ ]ou[[ ]]; use$(( ))para expressões. - Para comparações numéricas, use
-eq,-ne,-lt, etc., em[ ]ou(( ))em Bash.
Exercícios
Escreva um script que calcule a área de um círculo de raio 5 (use π=3.1416). Use aritmética de ponto flutuante com bc.
✓ Resposta:#!/bin/bash raio=5 pi=3.1416 area=$(echo "scale=2; $pi * $raio * $raio" | bc) echo "Área: $area"Dado um número de segundos, converta para horas, minutos e segundos. Exemplo: 3661 segundos → 1 hora, 1 minuto, 1 segundo.
✓ Resposta:#!/bin/bash segundos=3661 horas=$((segundos / 3600)) minutos=$(( (segundos % 3600) / 60 )) seg=$(( segundos % 60 )) echo "$horas hora(s), $minutos minuto(s), $seg segundo(s)"Use o operador módulo para verificar se um número é par ou ímpar. Escreva um script que receba um número como argumento e imprima "par" ou "ímpar".
✓ Resposta:#!/bin/bash if [ $# -eq 0 ]; then echo "Uso: $0 número" exit 1 fi if [ $(( $1 % 2 )) -eq 0 ]; then echo "par" else echo "ímpar" fiCalcule o fatorial de um número inteiro positivo usando aritmética inteira em Bash. Por exemplo, fatorial 5 = 120.
✓ Resposta:#!/bin/bash fatorial=1 for (( i=1; i<=$1; i++ )); do fatorial=$((fatorial * i)) done echo $fatorialEscreva um script que calcule a média de três notas fornecidas como argumentos, com duas casas decimais. Use bc.
✓ Resposta:#!/bin/bash if [ $# -ne 3 ]; then echo "Uso: $0 nota1 nota2 nota3" exit 1 fi soma=$(echo "$1 + $2 + $3" | bc) media=$(echo "scale=2; $soma / 3" | bc) echo "Média: $media"