Em shell script, o tratamento de strings e variáveis é fortemente influenciado pelo uso de aspas e caracteres de escape. Compreender as diferenças entre aspas simples e duplas, como escapar caracteres especiais, como ocorre a expansão de variáveis e o fenômeno de word splitting é essencial para escrever scripts robustos e previsíveis. Esta aula explora cada um desses tópicos com exemplos práticos.

O shell interpreta muitos caracteres de forma especial (espaços, $, ", ', \, etc.). As aspas e o escape são mecanismos para controlar essa interpretação, permitindo que você use esses caracteres literalmente ou force uma expansão desejada.

Aspas simples vs duplas

Aspas simples ('...') preservam o conteúdo literalmente: nenhuma expansão de variáveis, substituição de comandos ou interpretação de escapes (exceto a própria aspa simples, que não pode aparecer dentro). Já aspas duplas ("...") permitem expansão de variáveis ($var), substituição de comandos ($(comando)) e interpretam alguns escapes (como \, ", \$, \`, \n).

Exemplo prático:

#!/bin/bash
nome="João"
echo 'Olá, $nome'   # Imprime: Olá, $nome
echo "Olá, $nome"   # Imprime: Olá, João

Use aspas simples quando quiser uma string literal. Use aspas duplas quando precisar de expansão de variáveis, mas ainda quiser evitar word splitting (veja adiante).

Escape

O caractere backslash (\) escapa o próximo caractere, removendo seu significado especial. Por exemplo, \$ imprime um cifrão literal, \\ imprime uma barra invertida, \" imprime uma aspa dupla literal. Dentro de aspas duplas, alguns escapes continuam funcionando (\", \\, \$, \`), mas outros não (\n não é interpretado como nova linha, a menos que seja em $'...').

Exemplo:

#!/bin/bash
echo "Custo: \$10"   # Imprime: Custo: $10
echo 'Custo: \$10'   # Imprime: Custo: \$10 (a barra é literal)
echo "Linha1\\nLinha2" # Imprime: Linha1\nLinha2 (literal)
echo $'Linha1\\nLinha2' # Imprime: Linha1 (nova linha) Linha2 (usando $'...')

O escape é útil para incluir caracteres especiais em strings, mas prefira aspas simples para evitar confusão.

Expansão de variáveis

Variáveis são expandidas com $var ou ${var}. A forma com chaves é útil para desambiguar, por exemplo: ${var}texto. Expansão também ocorre em substituição de comandos: $(comando) ou `comando`. Aspas duplas permitem expansão; aspas simples não.

Exemplo:

#!/bin/bash
nome="Maria"
echo "$nome"          # Maria
echo '${nome}'        # ${nome} literal
echo "$nome é amiga"  # Maria é amiga
echo "${nome} é amiga" # Maria é amiga (mesmo)
echo "$nome_é amiga"  # (vazio, pois $nome_é é interpretado como variável)
echo "${nome}_é amiga" # Maria_é amiga

Expansão de variáveis também pode ser modificada com operadores: ${var:-padrão}, ${var:?mensagem}, etc. Isso é útil para fornecer valores padrão ou verificar se a variável está definida.

Word splitting

Word splitting é o processo pelo qual o shell divide uma string em palavras separadas por caracteres do IFS (Internal Field Separator), que por padrão são espaço, tab e nova linha. Isso ocorre após expansão de variáveis e substituição de comandos, a menos que a expansão esteja entre aspas duplas. Sem aspas, o resultado da expansão é sujeito a word splitting e globbing (expansão de padrões como *).

Exemplo:

#!/bin/bash
arquivos="file1.txt file2.txt"
# Sem aspas: word splitting separa em dois argumentos
for f in $arquivos; do echo "$f"; done
# Com aspas: preserva a string como um único argumento
for f in "$arquivos"; do echo "$f"; done

O word splitting é uma fonte comum de bugs. Sempre coloque variáveis entre aspas duplas a menos que você explicitamente queira splitting e globbing. Por exemplo, ao iterar sobre uma lista de arquivos separados por espaço, você pode querer splitting, mas cuidado com nomes de arquivos com espaços.

Boas práticas

  • Sempre use aspas duplas ao redor de variáveis: "$var".
  • Use aspas simples para strings literais, especialmente quando contêm caracteres especiais.
  • Use printf em vez de echo para maior controle sobre escapes e formatação.
  • Evite usar eval; prefira substituições seguras.
  • Teste scripts com shellcheck para detectar problemas com aspas.

Referências

Exercícios

  1. Qual a diferença entre '$HOME' e "$HOME"?

    ✓ Resposta: '$HOME' imprime literalmente $HOME, enquanto "$HOME" expande a variável e imprime o caminho do diretório home.
  2. O que o seguinte script imprime? echo "A barra invertida: \\"

    ✓ Resposta: Imprime: A barra invertida: \ (uma barra invertida). O primeiro \\ escapa o segundo, resultando em uma barra literal.
  3. Explique por que for f in $(ls) é problemático e como corrigir.

    ✓ Resposta: O comando $(ls) sofre word splitting e globbing, quebrando nomes de arquivos com espaços. A correção é usar um glob: for f in *; do ...; done ou for f in "$(ls)" (mas isso trata a saída como uma única string). Melhor: for f in *; do ...; done.
  4. Escreva um comando que atribua à variável saudacao o valor "Olá, mundo!" e depois imprima o número de caracteres da string (dica: use ${#var}).

    ✓ Resposta:
    saudacao="Olá, mundo!"
    echo ${#saudacao}   # Imprime: 11
  5. Qual a saída do script? var="a b c"; echo $var; echo "$var"

    ✓ Resposta: O primeiro echo $var imprime a b c (mas word splitting separa em três argumentos, o echo os une com espaços). O segundo echo "$var" imprime a b c (preserva a string). Na prática, ambos parecem iguais, mas o primeiro poderia causar problemas se houvesse globbing ou se IFS fosse alterado.