Eu tenho essa linha de código que lê um arquivo de texto linha por linha.
O arquivo de texto às vezes é gerado por um usuário do Windows, às vezes por um usuário do Unix. Portanto, às vezes vejo \r\n
no final da linha e às vezes vejo apenas \n
.
Eu quero que meu script seja capaz de lidar com os dois cenários e alcançar cada linha separadamente, independentemente de a quebra de linha ser \r
, ou \n
, ou \r\n
, ou \n\r
.
while read -r textFileLines; do ... something ...; done < text_file.txt
Este código funciona com \n\r
(LF CR) no final de cada linha, mas NÃO funciona quando tenho \r\n
no final da linha!
TESTE
Crie um novo arquivo de texto usando
Notepad++ v7.5.4
while read -r LINE; do echo "$LINE"; done < /cygdrive/d/test_text.txt
saída no Terminal:
first_line second_line third_string
Por que a fourth_output
linha não é mostrada?
Na sua imagem, o arquivo está sem a nova linha no final da última linha.
read
retorna true somente se ler o delimitador (newline) e, como não está no final da última linha,read
retorna false, seu loop termina e a última linha incompleta não é impressa.Isso não tem nada a ver com os retornos de carro, o comportamento é o mesmo mesmo com apenas NL, se a última linha estiver faltando o NL.
Aqui,
file1
tem duas linhas com terminações de linha CRLF:file2
está faltando a linha que termina na segunda linha:Se você quiser que o loop também processe o fragmento de linha final, você terá que verificar se a
read
variável contém algum dado quandoread
ela mesma retornar falha:Se você quiser se livrar do CR, você pode removê-lo dentro do loop, por exemplo
x=${x%$'\r'};
(em Bash/ksh/zsh), ou pré-processar o arquivo comtr -d '\r'
oudos2unix
ou algo assim.Existem ferramentas explícitas disponíveis para fazer isso. o mais comum que pode ser usado para remover
\r\n
arquivos é chamadodos2unix
.Se isso não estiver disponível em seu sistema, você pode usar um dos seguintes comandos para fazer algo semelhante em sua
awk sed 1 sed 2 trtextFileLines
variável:É claro que existem muitas outras maneiras de fazer isso, essas são apenas algumas das mais comuns.
Referências
Se você tiver alguns arquivos que são arquivos de texto DOS e alguns que são arquivos de texto Unix, seu script pode passar todos os dados por
dos2unix
:Os arquivos de texto Unix não seriam modificados por isso.
Para lidar adicionalmente com quebras de linha do Mac, acredito que você deve ser capaz de fazer
A última linha não é emitida pelo seu
read
loop, pois não é finalizada e, portanto, não é uma linha.Para detectar se um arquivo não possui uma nova linha final na última linha e adicionar uma se não tiver, em
bash
:Relacionado:
Executar:
Todos os problemas resolvidos.
Descrição:
Para corrigir a última nova linha ausente, use:
O que adicionará uma nova linha à direita somente se necessário (não alterará um arquivo correto).
Então, você pode converter
\r\n
(estilo DOS) para\n
(basta remover um \r no final da linha)\n\r
(estilo DOS inválido?) para um\n
(remover \r no início da linha)\r
(MAC antigo) para\n
em apenas uma chamada de (GNU) sed com:
Se o arquivo de texto for como este arquivo de teste: