Aspas e expansão
Esta aula aborda o uso de aspas simples e duplas, escape, expansão de variáveis e word splitting em shell script, explicando como cada um afeta a interpretação de comandos e variáveis. O conteúdo inclui exemplos práticos e boas práticas para evitar erros comuns.
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ãoUse 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_é amigaExpansã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"; doneO 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
printfem vez deechopara maior controle sobre escapes e formatação. - Evite usar
eval; prefira substituições seguras. - Teste scripts com
shellcheckpara detectar problemas com aspas.
Referências
- Bash Manual: Quoting
- Bash Manual: Shell Parameter Expansion
- Bash Manual: Word Splitting
- Greg's Wiki: Quotes
- ShellCheck - find bugs in your shell scripts
Exercícios
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.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.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 ...; doneoufor f in "$(ls)"(mas isso trata a saída como uma única string). Melhor:for f in *; do ...; done.Escreva um comando que atribua à variável
saudacaoo valor "Olá, mundo!" e depois imprima o número de caracteres da string (dica: use${#var}).✓ Resposta:saudacao="Olá, mundo!" echo ${#saudacao} # Imprime: 11Qual a saída do script?
var="a b c"; echo $var; echo "$var"✓ Resposta: O primeiroecho $varimprimea b c(mas word splitting separa em três argumentos, oechoos une com espaços). O segundoecho "$var"imprimea b c(preserva a string). Na prática, ambos parecem iguais, mas o primeiro poderia causar problemas se houvesse globbing ou seIFSfosse alterado.