Expansão de parâmetros
Aula sobre expansão de parâmetros em shell script, cobrindo valores padrão, substring, substituição de padrão e comprimento de strings, com exemplos práticos e exercícios.
A expansão de parâmetros é um recurso poderoso do shell que permite manipular variáveis de forma dinâmica, evitando a necessidade de comandos externos como sed ou awk para operações comuns em strings. Nesta aula, vamos explorar quatro tipos principais de expansão: valores padrão, extração de substring, substituição de padrão e obtenção de comprimento. Essas técnicas são essenciais para escrever scripts mais concisos e eficientes.
Dominar a expansão de parâmetros é fundamental para qualquer profissional que trabalhe com automação em Linux. Além de reduzir a complexidade do código, essas operações são executadas diretamente pelo shell, sem a criação de subprocessos, o que melhora a performance em scripts que processam grandes volumes de dados.
Valores padrão (${var:-})
A expansão ${var:-palavra} retorna o valor de var se ela estiver definida e não for nula; caso contrário, retorna palavra. Isso é útil para fornecer valores padrão sem modificar a variável original. Existe também ${var:=palavra}, que atribui o valor padrão à variável se ela não estiver definida.
Por exemplo, em um script que aceita um diretório de saída opcional, podemos usar ${OUTPUT_DIR:-/tmp} para usar /tmp se a variável não for definida. Já ${var:+palavra} retorna palavra se a variável estiver definida e não nula, caso contrário retorna nulo. E ${var:?mensagem} exibe uma mensagem de erro e termina o script se a variável não estiver definida.
#!/bin/bash
# Exemplo de valores padrão
nome=""
echo "Olá, ${nome:-visitante}!" # Saída: Olá, visitante!
nome="Maria"
echo "Olá, ${nome:-visitante}!" # Saída: Olá, Maria!
# Usando := para atribuir valor padrão
echo "Antes: ${data:=hoje}" # data não definida, assume 'hoje' e atribui
echo "Depois: $data" # Saída: hoje
# Usando :? para abortar se variável não definida
# Descomente a linha abaixo para testar:
# echo "Arquivo: ${arquivo:?Arquivo não especificado}"
Substring
A expansão ${var:posição} retorna a substring de var a partir de posição (base 0). ${var:posição:comprimento} retorna até comprimento caracteres. Se posição for negativo, conta a partir do final da string (requer um espaço ou parênteses para evitar ambiguidade com ${var:-}).
Essa funcionalidade elimina a necessidade de usar cut ou expr substr em muitos casos. Por exemplo, para extrair a extensão de um arquivo: ${arquivo##*.} é mais comum, mas substring também pode ser usado se soubermos a posição do ponto.
#!/bin/bash
frase="Aprendendo Shell Script"
echo "${frase:11}" # Saída: Shell Script
echo "${frase:11:5}" # Saída: Shell
echo "${frase: -6}" # Saída: Script (note o espaço antes do -6)
echo "${frase: -6:3}" # Saída: Scr
Substituição de padrão
O shell permite substituir partes de uma string que correspondam a um padrão. ${var/padrão/substituto} substitui a primeira ocorrência; ${var//padrão/substituto} substitui todas. ${var/#padrão/substituto} substitui se o padrão estiver no início; ${var/%padrão/substituto} substitui se estiver no final.
Essas operações são muito usadas para manipular caminhos de arquivos, renomear arquivos em lote, ou limpar strings. Por exemplo, ${caminho%/*} retorna o diretório pai (removendo o menor sufixo que corresponda a /*), e ${caminho##*/} retorna o nome do arquivo.
#!/bin/bash
url="https://exemplo.com/arquivo.txt"
echo "${url#*/}" # Remove a parte até a primeira barra: /exemplo.com/arquivo.txt
echo "${url##*/}" # Remove até a última barra: arquivo.txt
echo "${url%/*}" # Remove a última barra e tudo após: https://exemplo.com
echo "${url%.*}" # Remove a extensão: https://exemplo.com/arquivo
# Substituir todas as ocorrências de 'e' por 'E'
echo "${url//e/E}" # Saída: https://ExEmplo.com/arquivo.txt
Comprimento
O comprimento de uma string é obtido com ${#var}. Isso retorna o número de caracteres. É útil para validações (tamanho mínimo/máximo) ou para iterar sobre strings.
Para arrays, ${#array[@]} retorna o número de elementos, e ${#array[i]} retorna o comprimento do elemento no índice i.
#!/bin/bash
frase="Olá, mundo!"
echo "Comprimento: ${#frase}" # Saída: 12
# Array
arr=("um" "dois" "três")
echo "Número de elementos: ${#arr[@]}" # Saída: 3
echo "Comprimento do primeiro: ${#arr[0]}" # Saída: 2
Boas práticas
Sempre use aspas duplas ao redor das expansões para preservar espaços e evitar word splitting. Por exemplo, "${var:-padrão}". Prefira ${var:-} a ${var-} quando quiser tratar strings vazias como não definidas. Use ${var:?} para validar parâmetros obrigatórios.
Referências
- GNU Bash Manual - Shell Parameter Expansion
- Advanced Bash-Scripting Guide - Parameter Substitution
- Bash Hackers Wiki - Parameter Expansion
- man bash - Parameter Expansion
- ShellCheck - Static analysis for shell scripts
Exercícios
- Escreva um comando que, dada a variável
nome="João Silva", exiba "Olá, João!" usando expansão de parâmetros para extrair o primeiro nome. - Usando a variável
caminho="/home/usuario/documentos/arquivo.txt", extraia apenas o diretório (sem o nome do arquivo) usando expansão de parâmetros. - Crie uma variável
texto="O rato roeu a roupa do rei de Roma"e substitua todas as ocorrências de "ro" por "**" usando expansão de parâmetros. - Dada a variável
data="2024-12-25", extraia o mês (dois dígitos) usando substring. - Escreva um script que verifique se a variável
ARQUIVOestá definida e não é vazia; se não estiver, exiba uma mensagem de erro e saia com código 1. Use expansão de parâmetros.
echo "Olá, ${nome%% *}!"
Explicação: ${nome%% *} remove o maior sufixo que começa com espaço, deixando apenas o primeiro nome.
echo "${caminho%/*}"
Explicação: ${caminho%/*} remove o menor sufixo que corresponde a /*, ou seja, a última barra e tudo após.
echo "${texto//ro/**}"
Explicação: ${texto//ro/**} substitui globalmente todas as ocorrências de "ro" por "**".
echo "${data:5:2}"
Explicação: O mês começa na posição 5 (base 0) e tem comprimento 2.
: "${ARQUIVO:?Erro: ARQUIVO não definido ou vazio}"
Explicação: O comando : (no-op) é usado para que a expansão seja avaliada. Se a variável for nula ou não definida, o shell exibe a mensagem e termina com código 1.