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 let apenas se precisar de compatibilidade com versões muito antigas do Bash.
  • Para ponto flutuante, utilize bc com scale adequado 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

Exercícios

  1. 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"
    
  2. Crie um script que use o comando let para incrementar uma variável de 0 a 10 em um loop while e exiba o valor a cada iteração.

    ✓ Resposta:
    #!/bin/bash
    
    i=0
    while [ $i -le 10 ]; do
        echo "i = $i"
        let "i += 1"
    done
    
  3. Escreva 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"
    
  4. Use bc para 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"
    
  5. 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"