Variáveis são um dos conceitos mais fundamentais em qualquer linguagem de programação, e no Bash não é diferente. Elas permitem armazenar valores como números, strings, caminhos de arquivos e resultados de comandos, tornando seus scripts dinâmicos e reutilizáveis. Nesta aula, vamos explorar como criar, acessar e gerenciar variáveis no Bash, cobrindo desde a sintaxe básica até nuances importantes como aspas e escopo.

Dominar o uso de variáveis é essencial para escrever scripts eficientes e evitar erros comuns. Veremos que, no Bash, a atribuição tem regras específicas (sem espaços) e que o uso de chaves ${} pode evitar ambiguidades. Também discutiremos o comportamento das aspas simples e duplas, que afetam a expansão de variáveis, e o conceito de escopo global e local.

Atribuição (sem espaços)

No Bash, para criar uma variável, você simplesmente escreve o nome da variável seguido do sinal de igual (=) e o valor desejado. Uma regra crítica é que não pode haver espaços em branco ao redor do sinal de igual. Isso ocorre porque o Bash interpreta espaços como separadores de comandos e argumentos. Se você escrever nome = "João", o Bash tentará executar o comando nome com argumentos = e "João", resultando em um erro.

Os nomes de variáveis devem começar com uma letra ou sublinhado (_), seguidos de letras, números ou sublinhados. Eles são case-sensitive, ou seja, nome e NOME são variáveis diferentes. Além disso, por convenção, variáveis de ambiente costumam ser em maiúsculas, mas isso não é obrigatório.

Exemplos de atribuição:

#!/bin/bash
# Atribuição simples
nome="Maria"
idade=30
caminho="/home/usuario/documentos"

# Atribuição com resultado de comando (usando $() )
usuario=$(whoami)

# Atribuição com aspas simples (sem expansão)
frase='Olá, $nome'  # O conteúdo será literal, não expande $nome

# Exibindo os valores
echo "Nome: $nome"
echo "Idade: $idade"
echo "Caminho: $caminho"
echo "Usuário: $usuario"
echo "Frase: $frase"

Observe que ao atribuir uma string com espaços, você deve usar aspas (duplas ou simples) para que o valor seja tratado como uma única palavra. Sem aspas, o Bash interpretaria os espaços como separadores e você teria múltiplos argumentos, o que causaria erro na atribuição. Por exemplo, nome=João Silva tentaria executar o comando Silva com a variável nome definida como João.

Uso ($var e ${var})

Para acessar o valor de uma variável, você usa o cifrão ($) antes do nome. A forma mais comum é $var, mas há também a forma com chaves ${var}. Ambas geralmente funcionam da mesma maneira, mas a versão com chaves é mais segura em certos contextos, especialmente quando a variável é seguida por outros caracteres que poderiam ser interpretados como parte do nome.

Por exemplo, se você tem uma variável nome e deseja concatená-la com o sufixo _arquivo, escrever $nome_arquivo faria o Bash interpretar nome_arquivo como o nome da variável (que provavelmente não existe). Com chaves, ${nome}_arquivo resolve corretamente.

Além disso, a sintaxe ${var} permite o uso de operadores de expansão, como substituição de padrões e valores padrão, que veremos em aulas futuras. Por enquanto, lembre-se de que usar chaves é uma boa prática para evitar ambiguidades.

Exemplo de uso:

#!/bin/bash
nome="Ana"
# Uso simples
echo "Olá, $nome"

# Uso com chaves para desambiguar
arquivo="${nome}_dados.txt"
echo "Arquivo: $arquivo"

# Exemplo de ambiguidade sem chaves (comentado para não executar)
# echo "Olá, $nomeSilva"  # Tentaria a variável nomeSilva

# Exemplo correto com chaves
echo "Olá, ${nome}Silva"

Aspas

No Bash, as aspas têm funções distintas em relação à expansão de variáveis. Aspas duplas (") permitem a expansão de variáveis e substituição de comandos, mas inibem a divisão de palavras e a expansão de globs (curingas). Aspas simples (') suprimem toda expansão: o conteúdo é tratado literalmente, sem interpretar $, crases ou outros caracteres especiais.

É crucial entender essa diferença para evitar resultados inesperados. Por exemplo, se você quer exibir uma mensagem com o valor de uma variável, deve usar aspas duplas. Se usar aspas simples, verá o nome da variável em vez do valor.

Outro ponto: ao usar aspas duplas, o Bash ainda interpreta certos caracteres de escape, como \n (nova linha), \t (tab), e \$ para escapar um cifrão literal. Dentro de aspas simples, esses escapes não são processados.

Exemplo:

#!/bin/bash
nome="Carlos"

# Aspas duplas: expande a variável
echo "Olá, $nome"   # Saída: Olá, Carlos

# Aspas simples: não expande
echo 'Olá, $nome'   # Saída: Olá, $nome

# Aspas duplas com escape de cifrão
echo "Custo: \$10"  # Saída: Custo: $10

# Aspas duplas preservam espaços e caracteres especiais
frase="Linha 1
Linha 2"
echo "$frase"

Escopo básico

No Bash, por padrão, todas as variáveis têm escopo global dentro do script (e em subshells, dependendo de como são chamadas). Isso significa que, uma vez definida, uma variável pode ser acessada em qualquer parte do script, inclusive dentro de funções, a menos que seja explicitamente declarada como local.

Para declarar uma variável local a uma função, usa-se a palavra-chave local. Isso é importante para evitar efeitos colaterais e conflitos de nomes, especialmente em scripts maiores. A declaração local só pode ser usada dentro de uma função.

Além disso, quando um script é executado, ele roda em um processo filho do shell que o invocou. Variáveis definidas no script não são automaticamente exportadas para processos filhos, a menos que você use o comando export. Isso é relevante para variáveis de ambiente.

Exemplo de escopo:

#!/bin/bash
# Variável global
mensagem="Olá do escopo global"

minha_funcao() {
    local mensagem_local="Olá do escopo local"
    echo "Dentro da função: $mensagem"
    echo "Local: $mensagem_local"
}

minha_funcao

echo "Fora da função: $mensagem"
# A variável local não está acessível fora
echo "Tentando acessar local: $mensagem_local"  # Saída vazia

# Exportando variáveis para subprocessos
export minha_variavel="exportada"
./outro_script.sh  # Se existir, pode acessar minha_variavel

Boas práticas

  • Sempre use aspas duplas ao expandir variáveis em comandos para evitar divisão de palavras e globbing indesejado.
  • Use chaves ${var} quando a variável estiver adjacente a outros caracteres.
  • Prefira nomes de variáveis em minúsculas para diferenciar de variáveis de ambiente (que são em maiúsculas).
  • Use local dentro de funções para evitar poluir o escopo global.
  • Valide se uma variável foi definida antes de usá-la, com ${var:-default} ou ${var:?mensagem}.

Exercícios

  1. Explique por que a atribuição nome = "João" (com espaços) falha no Bash. O que o shell tenta fazer?

    ✓ Resposta: O Bash interpreta espaços como separadores de tokens. A atribuição nome = "João" é vista como três tokens: nome, = e "João". O shell tenta executar o comando nome com argumentos = e "João", o que gera um erro (comando não encontrado). A sintaxe correta não permite espaços ao redor do sinal de igual.
  2. Escreva um comando que atribua à variável saudacao o valor "Olá, mundo!" usando aspas duplas e outro usando aspas simples. Qual é a diferença prática se a string contiver $HOME?

    ✓ Resposta: Com aspas duplas: saudacao="Olá, $HOME" expande $HOME para o diretório home (ex.: /home/usuario). Com aspas simples: saudacao='Olá, $HOME' mantém o literal $HOME. Portanto, a diferença é a expansão de variáveis: aspas duplas expandem, aspas simples não.
  3. Dado o trecho fruta="maçã", escreva um comando que imprima maçãs (com "s" no final) usando a variável fruta. Explique por que você precisa de chaves.

    ✓ Resposta: O comando é echo "${fruta}s". Sem chaves, $frutas seria interpretado como uma variável chamada frutas, que não existe, resultando em uma string vazia seguida de "s". As chaves delimitam o nome da variável, permitindo que caracteres adicionais sejam concatenados corretamente.
  4. Dentro de uma função, você deseja criar uma variável temporária que não interfira em outras partes do script. Como você declara essa variável e por que isso é importante?

    ✓ Resposta: Usa-se a palavra-chave local antes da atribuição, por exemplo: local temp="valor". Isso limita o escopo da variável à função atual, evitando que ela sobrescreva variáveis globais ou cause efeitos colaterais fora da função. É importante para manter a modularidade e evitar bugs difíceis de rastrear.
  5. Qual é a diferença entre export MINHA_VAR e simplesmente definir MINHA_VAR sem exportar? Dê um exemplo de quando isso é relevante.

    ✓ Resposta: Definir uma variável sem exportar torna-a disponível apenas no shell atual (e em funções) mas não em processos filhos. export marca a variável para ser passada a qualquer subprocesso criado a partir do shell. Por exemplo, se um script define CONFIG="produção" e depois executa um programa externo que espera essa variável, é necessário usar export CONFIG para que o programa a enxergue.

Referências