Quebra de Linha: três convenções diferentes, o mesmo conceito visual
Uma "quebra de linha" não é um único caractere universal — é, na
prática, representada de três formas diferentes dependendo da origem
do arquivo de texto: \n (Line Feed, o padrão em Unix,
Linux e macOS moderno), \r\n (Carriage Return + Line
Feed, o padrão histórico do Windows, herdado de convenções de máquina
de escrever/teletipo onde "retornar o carro" e "avançar a linha" eram
operações fisicamente separadas), e \r sozinho (usado
pelo Mac OS clássico, anterior ao macOS baseado em Unix — hoje raro,
mas ainda aparece em arquivos legados ou exportados por sistemas mais
antigos).
Por que arquivos "baixados no Windows" às vezes mostram linhas extras
Um sintoma real e comum dessa divergência: um arquivo de texto criado
no Windows (com \r\n) processado por uma ferramenta que
espera só \n pode exibir um caractere de retorno de carro
"sobrando" no final de cada linha — visualmente invisível na maioria
dos editores modernos, mas presente nos dados, e causando efeitos
colaterais reais como uma comparação de string que deveria ser igual
falhando silenciosamente ("linha1" lido de um arquivo Unix não é
idêntico, byte a byte, a "linha1\r" lido de um arquivo Windows, mesmo
parecendo visualmente igual). Scripts que processam arquivo de
configuração ou dado tabular entre sistemas operacionais diferentes
são o cenário mais comum onde esse tipo de bug aparece.
Normalizar antes de processar, não depois de um bug aparecer
A prática recomendada para qualquer pipeline que processa texto de
origem incerta (upload de usuário, arquivo recebido por e-mail,
conteúdo colado de fontes diferentes) é normalizar todas as
convenções de quebra de linha para uma única forma padrão logo na
entrada do sistema — tipicamente substituindo \r\n e
\r isolados por \n — antes de qualquer
processamento posterior (contagem de linhas, parsing, comparação).
Fazer isso de forma reativa, só depois de um bug de comparação ou
contagem aparecer em produção, é mais custoso do que normalizar
proativamente na fronteira de entrada do sistema.