Parâmetros posicionais
Esta aula aborda os parâmetros posicionais em shell script, explicando como acessar argumentos da linha de comando com $1, $2, $@, $*, $# e a instrução shift. O conteúdo inclui exemplos práticos, boas práticas e exercícios com respostas.
Em shell script, os parâmetros posicionais são variáveis especiais que permitem acessar os argumentos passados para um script ou função na linha de comando. Eles são fundamentais para criar scripts flexíveis e reutilizáveis, que podem receber entradas do usuário ou de outros programas. Nesta aula, vamos explorar as principais variáveis relacionadas a parâmetros posicionais: $1, $2, $@, $*, $# e o comando shift.
Dominar esses conceitos é essencial para qualquer desenvolvedor que deseja automatizar tarefas no Linux, pois permite que scripts se comportem de maneira dinâmica com base nos argumentos fornecidos. Veremos como cada um funciona, suas diferenças sutis e como usá-los em conjunto.
$1, $2
As variáveis $1, $2, $3, etc., representam o primeiro, segundo, terceiro argumento passado para o script ou função. Elas são chamadas de parâmetros posicionais porque sua posição na linha de comando determina qual variável recebe o valor. Por exemplo, se um script é chamado com ./script.sh foo bar, então $1 será "foo" e $2 será "bar".
É importante notar que $0 é uma variável especial que contém o nome do próprio script (ou da função, dependendo do contexto). Para acessar argumentos além do nono, é necessário usar chaves, como $ {10}, $ {11}, etc. Sem as chaves, o shell interpretaria $10 como $1 seguido de "0".
#!/bin/bash
# Exemplo de uso de $1 e $2
echo "Nome do script: $0"
echo "Primeiro argumento: $1"
echo "Segundo argumento: $2"
# Exemplo com argumento acima de 9
echo "Décimo argumento: ${10}"
Ao executar ./script.sh um dois tres quatro cinco seis sete oito nove dez, a saída será:
Nome do script: ./script.sh
Primeiro argumento: um
Segundo argumento: dois
Décimo argumento: dez
$@ e $*
Ambos $@ e $* representam todos os argumentos passados para o script, mas com uma diferença importante quando usados dentro de aspas duplas. $@ preserva cada argumento como uma palavra separada, mesmo que contenha espaços, enquanto $* combina todos os argumentos em uma única string, separada pelo primeiro caractere do IFS (normalmente espaço).
Na prática, "$@" é mais seguro e é a forma recomendada para iterar sobre os argumentos, pois mantém a integridade de cada um. Já "$*" pode causar problemas se algum argumento contiver espaços. Veja o exemplo:
#!/bin/bash
echo "Usando \"\$@\":"
for arg in "$@"; do
echo " - $arg"
done
echo "Usando \"\$*\":"
for arg in "$*"; do
echo " - $arg"
done
Se o script for chamado com ./script.sh "um dois" tres, a saída será:
Usando "$@":
- um dois
- tres
Usando "$*":
- um dois tres
Note que com "$*", todos os argumentos foram tratados como uma única string, perdendo a separação original.
$#
A variável $# contém o número de argumentos passados para o script (excluindo o nome do script). É útil para verificar se o usuário forneceu a quantidade correta de argumentos antes de prosseguir com a execução, evitando erros.
Exemplo de uso:
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Erro: Nenhum argumento fornecido."
echo "Uso: $0 <nome> [idade]"
exit 1
fi
echo "Número de argumentos: $#"
echo "Primeiro argumento: $1"
if [ $# -ge 2 ]; then
echo "Segundo argumento: $2"
fi
Se o script for executado sem argumentos, ele exibe uma mensagem de erro e sai com código 1. Caso contrário, mostra os argumentos conforme disponíveis.
shift
O comando shift desloca os parâmetros posicionais para a esquerda, descartando o primeiro argumento ($1) e movendo os demais uma posição para baixo: o antigo $2 torna-se $1, $3 torna-se $2, e assim por diante. Opcionalmente, pode-se passar um número para shift, indicando quantas posições deslocar (ex.: shift 2 descarta os dois primeiros argumentos).
O shift é frequentemente usado em loops para processar argumentos um a um, especialmente quando o script aceita opções ou flags. Exemplo:
#!/bin/bash
echo "Argumentos recebidos: $@"
while [ $# -gt 0 ]; do
echo "Processando: $1"
shift
done
echo "Todos os argumentos foram processados."
Executando ./script.sh a b c, a saída será:
Argumentos recebidos: a b c
Processando: a
Processando: b
Processando: c
Todos os argumentos foram processados.
Note que após o loop, $# é zero e os parâmetros posicionais foram esgotados.
Boas práticas
- Sempre use aspas duplas ao expandir
$@("$@") para preservar argumentos com espaços. - Verifique
$#antes de usar$1,$2, etc., para evitar erros de argumentos faltantes. - Use
shiftcom cuidado: faça uma cópia dos argumentos se precisar deles depois. - Para argumentos opcionais, use valores padrão com
$ {1:-default}.
Referências
- GNU Bash Manual: Positional Parameters
- Advanced Bash-Scripting Guide: Other Types of Variables
- Shell Scripting Tutorial: Variables - Part 1
- Linuxize: Bash Positional Parameters
- Bash Hackers Wiki: Positional Parameters
Exercícios
-
Escreva 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.
✓ Resposta:
#!/bin/bash if [ $# -ne 2 ]; then echo "Erro: São necessários exatamente 2 argumentos." echo "Uso: $0 <num1> <num2>" exit 1 fi soma=$(( $1 + $2 )) echo "A soma de $1 e $2 é $soma." -
Crie um script que imprima todos os argumentos passados, um por linha, usando
"$@".✓ Resposta:#!/bin/bash echo "Lista de argumentos:" for arg in "$@"; do echo "$arg" done -
Faça um script que exiba o número de argumentos e o primeiro e último argumento (dica: use shift para chegar ao último).
✓ Resposta:
#!/bin/bash if [ $# -eq 0 ]; then echo "Nenhum argumento fornecido." exit 1 fi primeiro=$1 # Desloca até o último argumento while [ $# -gt 1 ]; do shift done ultimo=$1 echo "Número de argumentos: $#" echo "Primeiro argumento: $primeiro" echo "Último argumento: $ultimo" -
Escreva um script que aceite uma lista de nomes de arquivos e exiba apenas aqueles que existem no diretório atual. Use
shiftpara processar cada argumento.✓ Resposta:#!/bin/bash if [ $# -eq 0 ]; then echo "Nenhum arquivo especificado." exit 1 fi echo "Arquivos existentes:" while [ $# -gt 0 ]; do if [ -f "$1" ]; then echo "$1" fi shift done -
Crie um script que aceite opções:
-vpara modo verboso e-n <nome>para definir um nome. Useshiftpara processar as opções. Se nenhuma opção for passada, exiba uma mensagem padrão.✓ Resposta:#!/bin/bash verbose=false nome="" while [ $# -gt 0 ]; do case "$1" in -v) verbose=true shift ;; -n) if [ $# -lt 2 ]; then echo "Erro: -n requer um argumento." exit 1 fi nome="$2" shift 2 ;; *) echo "Opção desconhecida: $1" exit 1 ;; esac done if [ "$verbose" = true ]; then echo "Modo verboso ativado." fi if [ -n "$nome" ]; then echo "Olá, $nome!" else echo "Olá, mundo!" fi