Parâmetros posicionais são variáveis especiais no Bash que armazenam os argumentos passados para um script ou função. Eles permitem que scripts sejam mais dinâmicos e reutilizáveis, processando entradas fornecidas pelo usuário ou por outros programas. Nesta aula, exploraremos como acessar esses parâmetros individualmente, como trabalhar com todos eles de uma vez, como contar quantos foram fornecidos e como deslocá-los com o comando shift.

Dominar esses conceitos é essencial para criar scripts que aceitem opções e argumentos de forma flexível, algo comum em ferramentas de linha de comando. Vamos detalhar cada tópico com exemplos práticos.

$1, $2

As variáveis $1, $2, ..., $9 representam o primeiro, segundo, nono argumento posicional, respectivamente. Para argumentos além do nono, é necessário usar chaves: ${10}, ${11}, etc. Essas variáveis são preenchidas automaticamente quando o script é invocado ou quando uma função é chamada.

Exemplo: suponha um script chamado saudacao.sh que recebe um nome e uma saudação como argumentos.

#!/bin/bash
echo "$1, $2!"

Ao executar ./saudacao.sh Olá Mundo, a saída será Olá, Mundo!. Note que $1 é "Olá" e $2 é "Mundo".

É importante lembrar que esses parâmetros são apenas leitura, mas podem ser reatribuídos via set comando.

$@ e $*

Ambos representam todos os argumentos passados ao script, mas com diferenças sutis no tratamento de aspas. $@ expande cada argumento como uma palavra separada, preservando espaços em argumentos entre aspas. $* expande todos os argumentos como uma única palavra, separando-os pelo primeiro caractere do IFS (normalmente espaço).

Exemplo para demonstrar a diferença:

#!/bin/bash
echo "Usando \$@:"
for arg in "$@"; do
    echo "  $arg"
done

echo "Usando \$*:"
for arg in "$*"; do
    echo "  $arg"
done

Execute com ./script.sh "um argumento" "outro argumento". A saída será:

Usando $@:
  um argumento
  outro argumento
Usando $*:
  um argumento outro argumento

Perceba que $* trata todos os argumentos como um único elemento. Por isso, é recomendado usar "$@" (com aspas duplas) para preservar a estrutura original dos argumentos, especialmente ao passá-los para outros comandos.

$#

A variável $# contém o número de argumentos posicionais fornecidos ao script ou função. É útil para validar se o usuário passou a quantidade correta de argumentos.

Exemplo de uso:

#!/bin/bash
if [ $# -eq 0 ]; then
    echo "Nenhum argumento fornecido."
else
    echo "Foram fornecidos $# argumentos."
fi

Se executar sem argumentos, exibe "Nenhum argumento fornecido." Caso contrário, mostra o número. É comum usar $# em verificações para exibir mensagens de uso.

shift

O comando shift desloca os parâmetros posicionais para a esquerda. Por padrão, shift remove o primeiro argumento ($1) e renumera os demais: o que era $2 torna-se $1, $3 vira $2, etc. É possível passar um número para deslocar mais de uma posição: shift N.

Exemplo de processamento de argumentos em loop com shift:

#!/bin/bash
while [ $# -gt 0 ]; do
    echo "Processando argumento: $1"
    shift
done

Esse loop itera sobre todos os argumentos, imprimindo um por vez, e vai removendo-os até que não haja mais argumentos ($# chega a zero). É uma técnica comum para implementar opções de linha de comando (ex.: -v, --verbose).

Boas práticas

Sempre que possível, use "$@" (com aspas duplas) para preservar argumentos com espaços. Evite modificar $IFS desnecessariamente, pois pode afetar o comportamento de $*. Documente os parâmetros esperados no cabeçalho do script. Prefira opções nomeadas (com getopts) para scripts mais complexos, mas para scripts simples, parâmetros posicionais são suficientes.

Referências

Exercícios

  1. Crie um script que receba dois números como argumentos e imprima a soma deles. Se não forem fornecidos exatamente dois argumentos, exiba uma mensagem de erro.
  2. ✓ Resposta:
    #!/bin/bash
    if [ $# -ne 2 ]; then
        echo "Uso: $0 numero1 numero2"
        exit 1
    fi
    soma=$(( $1 + $2 ))
    echo "Soma: $soma"
    
  3. Escreva um script que use $@ para imprimir cada argumento em uma linha separada, mas com a formatação: "Argumento X: valor".
  4. ✓ Resposta:
    #!/bin/bash
    cont=1
    for arg in "$@"; do
        echo "Argumento $cont: $arg"
        ((cont++))
    done
    
  5. Faça um script que aceite uma lista de nomes de arquivos como argumentos e exiba apenas aqueles que existem (use -f). Use shift para processar.
  6. ✓ Resposta:
    #!/bin/bash
    while [ $# -gt 0 ]; do
        if [ -f "$1" ]; then
            echo "$1 existe"
        fi
        shift
    done
    
  7. Crie um script que simule um comando de soma de números passados como argumentos, usando $# para verificar se há pelo menos um argumento, e shift para somar todos.
  8. ✓ Resposta:
    #!/bin/bash
    if [ $# -eq 0 ]; then
        echo "Uso: $0 num1 [num2 ...]"
        exit 1
    fi
    soma=0
    while [ $# -gt 0 ]; do
        soma=$(( soma + $1 ))
        shift
    done
    echo "Soma total: $soma"
    
  9. Escreva um script que imprima o primeiro e o último argumento passados, usando $1 e ${$#} (dica: use eval ou indireção).
  10. ✓ Resposta:
    #!/bin/bash
    if [ $# -eq 0 ]; then
        echo "Nenhum argumento."
        exit 1
    fi
    echo "Primeiro: $1"
    # Para o último, usa indireção com ${!#}
    echo "Último: ${!#}"