Comando read: Entrada Interativa em Shell Scripts

Comando read: Entrada Interativa em Shell Scripts

"Quero que meu script pause e deixe o usuário digitar um nome ou senha." Quando você chega nesse momento, o comando read é a resposta. Neste artigo, Lina e Linny-senpai explicam passo a passo como capturar entrada do teclado e ler arquivos com read.

O Que Você Vai Aprender

  • O que o comando read faz e por que ele é importante
  • Como usar prompts (-p), entrada oculta (-s) e timeout (-t)
  • O clássico padrão while read para processar um arquivo linha por linha
  • Duas armadilhas para iniciantes: a "armadilha do pipe" e por que adicionar -r

1. O Que É o Comando read?

Conclusão: read é um builtin que lê uma linha da entrada padrão e armazena em uma variável, tornando seu script interativo.

Lina: Linny-senpai, eu estava escrevendo um shellUm programa interativo que interpreta os comandos digitados e os executa. script e cheguei num ponto onde quero que o usuário digite algo. Como faço isso?
Veterano Linny: É exatamente para isso que o comando read serve. read pega uma linha digitada no teclado e armazena em uma variável.

O que o read faz

read é um builtin do shell que lê uma linha da entrada padrão (como o teclado) e armazena em uma variável. Use sempre que quiser que o usuário insira algo e depois usar esse valor dentro do seu script.

Lina: Um "builtin" é diferente de comandos como ls ou cat?
Veterano Linny: Boa pergunta. ls e cat são comandos que existem como arquivos executáveis, como /bin/ls. Mas read é um recurso integrado ao próprio shell. Por isso which read geralmente não encontra nada. Tente type read e você verá read is a shell builtin.

2. O Uso Mais Básico

Conclusão: Digite read variável e o shell aguarda; a linha que você digitar antes de pressionar Enter vai para essa variável.

Lina: Quero experimentar agora mesmo. Me mostra a forma mais simples.
Veterano Linny: Digite isso. Depois de pressionar Enter, o cursor para e espera sua entrada.
read name
Lina: Parou. Então se eu digitar Lina aqui e pressionar Enter...?
Veterano Linny: O texto "Lina" vai para a variável name. Vamos verificar o que está dentro.
read name
Lina
echo "Hello, $name"
Hello, Lina

Adicione $ para ler o valor de uma variável

O valor que você armazenou com read name é recuperado adicionando um $ na frente, como em $name. Envolver em aspasEnvolver um texto entre aspas (' ou ") para que seja tratado como um único valor, por exemplo um que tenha espaços. duplas como echo "$name" é o estilo seguro: lida corretamente com valores que contêm espaços.

3. Exibindo um Prompt (-p)

Conclusão: read -p "mensagem" variável exibe um promptUm símbolo (como $ ou #) exibido quando o shell está esperando sua entrada. antes da entrada para que o usuário saiba o que digitar.

Lina: Mas se o cursor simplesmente parar em silêncio, o usuário não tem ideia do que digitar, certo?
Veterano Linny: Exatamente. Então normalmente usamos a opção -p para exibir uma mensagem de prompt junto com a entrada.
read -p "Enter your name: " name
echo "Welcome, $name"
Enter your name: Lina
Welcome, Lina
Lina: Legal. Agora ficou óbvio o que digitar.
Veterano Linny: Isso. A string após -p é impressa como está. Terminar com um espaço como : facilita a leitura da posição de entrada, então eu recomendo.

4. Lendo Vários Valores de Uma Vez

Conclusão: Liste vários nomes de variáveis após read e a entrada separada por espaços é distribuída em cada uma.

Lina: Posso pedir várias coisas de uma vez, como nome e sobrenome?
Veterano Linny: Sim. Liste os nomes das variáveis separados por espaços após read. Se a entrada também for separada por espaços, cada valor vai para a variável correspondente.
read -p "First and last name: " first last
echo "First: $first / Last: $last"
First and last name: Lina Yamada
First: Lina / Last: Yamada

Entrada extra vai para a última variável

Com read a b (duas variáveis) mas entrada 1 2 3 4, a recebe 1 e b recebe todo o restante (2 3 4). Se houver pouca entrada, as variáveis restantes ficam vazias.

5. Ocultando Entrada de Senha (-s)

Conclusão: read -s não exibe os caracteres digitados, então use para senhas e outros valores secretos.

Lina: Quando o usuário digita uma senha, mostrar na tela é um problema, não é?
Veterano Linny: É aí que entra a opção -s (silent). Os caracteres digitados não são exibidos na tela. Use ao ler senhas ou valores secretos.
read -s -p "Password: " pass
echo
echo "Characters entered: ${#pass}"
Password:
Characters entered: 8
Lina: Nada apareceu enquanto eu digitava, mas o valor foi capturado mesmo assim.
Veterano Linny: Isso. -s apenas oculta a exibição; o valor é armazenado com segurança na variável. Como -s também suprime a quebra de linha quando você pressiona Enter, adicionar um echo logo depois mantém a saída organizada. ${#pass} é a sintaxe para o comprimento de uma variável.

6. Adicionando um Limite de Tempo (-t)

Conclusão: read -t segundos faz o read desistir automaticamente se nenhuma entrada chegar dentro do tempo especificado.

Lina: Se ninguém digitar nada, o script fica travado para sempre, certo?
Veterano Linny: Para evitar isso, use -t (timeout). Ele espera o número de segundos especificado e segue em frente se não houver entrada.
if read -t 5 -p "Type within 5 seconds: " answer; then
    echo "You entered: $answer"
else
    echo
    echo "Time's up"
fi

Você pode testar se o read teve sucesso com if

read retorna "sucesso" quando lê uma linha, e "falha" em timeout ou fim da entrada (mais sobre isso abaixo). Capturar isso com if read ...; then permite ramificar com base em se a entrada chegou.

7. Lendo um Arquivo Linha por Linha (while read)

Conclusão: while read line; do ... done < arquivo puxa um arquivo para uma variável uma linha por vez para processamento.

Lina: Às vezes quero processar um arquivo linha por linha, não apenas entrada do teclado.
Veterano Linny: Para isso, a combinação while read é a mais adequada. Esse é um padrão clássico de shell scripting, então memorize a forma completa e você usará para sempre.
while read line; do
    echo "Read line: $line"
done < list.txt
Lina: O que é a parte < list.txt?
Veterano Linny: Isso é um redirecionamento, que significa "alimentar o conteúdo de list.txt no read." Cada vez que read lê uma linha, armazena em line e repete o loop até não haver mais linhas. Quando chega ao fim do arquivo, read retorna "falha", então o loop termina naturalmente.

Uma forma mais segura: while IFS= read -r line

Na prática, você verá frequentemente while IFS= read -r line; do ... done < file. A parte IFS= evita que espaços em branco iniciais e finais sejam removidos, e -r lê barras invertidas (\) literalmente. A próxima seção explica por que.

8. Duas Armadilhas que Iniciantes Encontram

Conclusão: Um while read via pipe roda em um processo separado, então suas variáveis desaparecem, e sem -r as barras invertidas somem.

Lina: Senpai, usei while read, mas um contador que incremento dentro do loop volta a 0 depois do loop... é um bug?
Veterano Linny: Esse é um clássico. Não é um bug; é causado por como os pipes funcionam. Vamos explicar.

Armadilha 1: Variáveis Dentro de um Pipe Não Sobrevivem

count=0
cat list.txt | while read line; do
    count=$((count + 1))
done
echo "$count"   # prints 0
Lina: Por que é 0? Estou contando corretamente dentro.
Veterano Linny: Quando você conecta com um pipe como cat ... | while ..., a parte while roda em um processo separado (um subshell). Incrementar count lá só muda um "clone." O count original nunca é atualizado.

Correção: use redirecionamento em vez de pipe

count=0
while read line; do
    count=$((count + 1))
done < list.txt
echo "$count"   # counts correctly

Com o redirecionamento < list.txt, while roda no mesmo processo, então a mudança em count sobrevive.

Armadilha 2: Sem -r, Barras Invertidas Desaparecem

Lina: E a outra, -r -- por que adicionamos?
Veterano Linny: Sem -r, read trata a barra invertida (\) como especial e a remove. Por exemplo, ler o caminhoUma sequência de texto que descreve a localização de um arquivo ou diretório. C:\UsersC:Users. Então, quando quiser ler a entrada exatamente como digitada, adicionar -r é a regra.
# Without -r: the backslashes are gone
read path <<< 'C:\Users\lina'; echo "$path"
# -> C:Userslina

# With -r: read literally
read -r path <<< 'C:\Users\lina'; echo "$path"
# -> C:\Users\lina

Na dúvida, adicione -r

A menos que tenha um motivo específico para não adicionar, usar -r no read é a escolha segura. Linters de shell script (como ShellCheck) também alertam sobre um read sem -r.

9. Um Exercício Rápido para Revisar

Lina: Aprendi bastante, então quero escrever algo eu mesma.
Veterano Linny: Ótimo. Aqui vai um pequeno desafio. Escreva um script que peça um nome e cumprimente o usuário de volta.
Exercício: escreva um script de saudação (clique para ver a solução)

Tarefa: Pergunte "What's your name?", depois use o nome digitado para imprimir "Hello, NAME!"

Solução exemplo:

#!/bin/bash
read -p "What's your name? " name
echo "Hello, ${name}!"

Ele mostra um prompt com -p e imprime o valor capturado com $name. Envolver como ${name} com chaves torna o limite da variável claro e seguro.

Lina: Pronto. Mostrar um prompt com read -p, depois exibir com $name.
Veterano Linny: Essa é a ideia. read é um comando curto, mas uma vez que você domina -p, -s, -t e while read, consegue lidar com quase qualquer situação de "capturar entrada". A partir daqui, basta continuar usando em scripts reais para ganhar fluência.

Resumo

Pontos-chave do comando read

  • read variavel armazena uma linha da entrada padrão em uma variável
  • -p "mensagem" exibe um prompt que pede a entrada
  • -s oculta a entrada da tela (bom para senhas)
  • -t segundos define um timeout na espera pela entrada
  • while read line; do ... done < arquivo processa um arquivo linha por linha
  • Use redirecionamento (< arquivo) em vez de pipe, e adicione -r, para a forma segura

Depois de dominar read, seus scripts evoluem de "coisas que simplesmente rodam sozinhas" para "coisas que interagem com o usuário." Em seguida, vá para Fundamentos de Shell Scripting para aprender a combinar a entrada capturada com condicionais e loops.