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, evitando let e expr (obsoleto).
  • Use bc com scale adequado 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

  1. 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"
    
  2. 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)"
    
  3. 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"
    fi
    
  4. Calcule 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 $fatorial
    
  5. Escreva 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"
    

Referências