Variáveis no Bash: declaração e expansão
1. Introdução às variáveis no Bash
No Bash, variáveis são espaços na memória que armazenam dados — desde números e textos até caminhos de arquivos e resultados de comandos. Diferentemente de linguagens compiladas, no shell tudo é tratado como string até que se prove o contrário.
Existem dois tipos principais: variáveis de ambiente (disponíveis para processos filhos) e variáveis locais (restritas ao shell atual). As variáveis de ambiente são herdadas por subprocessos, enquanto as locais desaparecem ao final do script ou sessão.
Quanto à nomenclatura:
- Nomes podem conter letras, números e underscores (_)
- Não podem começar com número
- Convenção: variáveis de ambiente em MAIÚSCULAS (PATH, HOME), variáveis locais em minúsculas (contador, nome_arquivo)
- Evite nomes reservados como if, then, else, for
# Válidos
nome="João"
contador=10
_PATH="/tmp"
# Inválidos
1nome="erro" # começa com número
meu-nome="erro" # hífen não permitido
2. Declaração e atribuição de variáveis
A sintaxe básica é simples: nome=valor. Não pode haver espaços ao redor do = — essa é uma das fontes mais comuns de erro para iniciantes.
# Atribuição básica
nome="Maria"
idade=30
Para valores com espaços ou caracteres especiais, use aspas:
# Com espaços
mensagem="Olá, mundo!"
caminho="/home/usuario/Meus Documentos"
# Com caracteres especiais
senha="pa$$word"
texto='Isto é um $literal (não expande)'
Para tornar uma variável imutável (readonly):
declare -r PI=3.14159
readonly URL="https://exemplo.com"
# Tentativa de alteração gera erro
PI=3.14 # bash: PI: readonly variable
3. Expansão de variáveis
A expansão é o mecanismo que substitui $variavel pelo seu valor. A forma mais básica é com $:
nome="Ana"
echo $nome # Ana
echo "$nome" # Ana (preserva espaços)
Use chaves ${variavel} quando precisar delimitar o nome:
prefixo="super"
echo "${prefixo}mercado" # supermercado
echo "$prefixomercado" # vazio (interpreta 'prefixomercado')
Expansão indireta permite acessar uma variável cujo nome está em outra:
cor_primaria="azul"
nome_variavel="cor_primaria"
echo ${!nome_variavel} # azul
O comando eval também faz expansão indireta, mas é menos seguro:
eval echo \$$nome_variavel # azul
4. Parâmetros de substituição (modificadores)
O Bash oferece operadores poderosos para tratar valores padrão e ausentes:
| Operador | Descrição | Exemplo |
|---|---|---|
${var:-padrao} |
Usa padrao se var não existir ou for nula |
echo "${nome:-Visitante}" |
${var:=padrao} |
Atribui padrao se var não existir ou for nula |
echo "${nome:=Visitante}" |
${var:+alternativo} |
Usa alternativo se var existir e não for nula |
echo "${nome:+presente}" |
${var:?mensagem} |
Exibe erro se var não existir ou for nula |
echo "${nome:?variável obrigatória}" |
Para obter o tamanho de uma string:
texto="Bash Script"
echo ${#texto} # 11
Para fatiar strings:
texto="Bash Script"
echo ${texto:0:4} # Bash
echo ${texto:5:6} # Script
echo ${texto: -6} # Script (espaço antes do -6)
5. Expansão de aritmética e comandos
A aritmética no Bash usa $(( expressao )):
a=10
b=3
echo $(( a + b )) # 13
echo $(( a * b )) # 30
echo $(( a ** 2 )) # 100 (potenciação)
O comando let faz o mesmo, mas sem eco:
let resultado=a+b
echo $resultado # 13
Substituição de comando executa um comando e retorna sua saída:
# Forma antiga (com crases)
data=`date +%Y-%m-%d`
# Forma moderna (recomendada)
data=$(date +%Y-%m-%d)
echo "Hoje é $data"
A forma $(comando) é preferível porque permite aninhamento fácil:
# Aninhamento com $()
arquivo=$(ls -la $(pwd))
# Com crases seria confuso
arquivo=`ls -la \`pwd\``
6. Remoção e substituição de padrões em strings
O Bash permite manipular strings com padrões (globbing):
Remoção de prefixo:
arquivo="documento.txt.bak"
echo ${arquivo#*.} # txt.bak (menor correspondência)
echo ${arquivo##*.} # bak (maior correspondência)
Remoção de sufixo:
arquivo="documento.txt.bak"
echo ${arquivo%.*} # documento.txt (menor)
echo ${arquivo%%.*} # documento (maior)
Substituição de padrões:
texto="O rato roeu a roupa do rei"
echo ${texto/rato/gato} # O gato roeu a roupa do rei (primeira ocorrência)
echo ${texto//r/g} # O gato goeu a goupa do gei (global)
echo ${texto/#O/A} # A rato roeu a roupa do rei (início)
echo ${texto/%rei/rainha} # O rato roeu a roupa da rainha (final)
7. Arrays no Bash
Arrays indexados (índices numéricos):
# Declaração
frutas=("maçã" "banana" "laranja")
# Atribuição direta
frutas[3]="uva"
# Acesso
echo ${frutas[0]} # maçã
echo ${frutas[@]} # maçã banana laranja uva
echo ${#frutas[@]} # 4 (tamanho)
Arrays associativos (chaves nomeadas) com declare -A:
declare -A capitais
capitais[SP]="São Paulo"
capitais[RJ]="Rio de Janeiro"
capitais[BA]="Salvador"
echo ${capitais[SP]} # São Paulo
echo ${!capitais[@]} # SP RJ BA (chaves)
8. Boas práticas e armadilhas comuns
Sempre use aspas duplas em expansões:
arquivo="meu arquivo.txt"
# Perigoso
rm $arquivo # tenta remover 'meu' e 'arquivo.txt'
# Correto
rm "$arquivo" # remove 'meu arquivo.txt'
Escopo com local dentro de funções:
minha_funcao() {
local var_local="visível apenas aqui"
global="visível em todo o script"
}
Diferença entre variável não definida, nula e vazia:
unset var1 # não definida
var2="" # definida, mas vazia
var3=" " # definida, não vazia (contém espaço)
echo ${var1:-padrao} # padrao
echo ${var2:-padrao} # padrao
echo ${var3:-padrao} # ' ' (espaço)
Use set -u no início do script para que variáveis não definidas causem erro, ajudando a detectar bugs.
Referências
- GNU Bash Manual - Shell Parameters — Documentação oficial sobre parâmetros e variáveis no Bash
- Bash Guide for Beginners - Variables — Tutorial introdutório sobre declaração e uso de variáveis
- Advanced Bash-Scripting Guide - Parameter Substitution — Guia avançado sobre substituição de parâmetros e modificadores
- Bash Hackers Wiki - Arrays — Referência completa sobre arrays indexados e associativos
- Shell Scripting Tutorial - Variables and Expansions — Tutorial prático com exemplos de expansão e boas práticas
- Greg's Wiki - Bash FAQ — Perguntas frequentes sobre variáveis, expansão e armadilhas comuns