Remover CRLF

Para manter o padrão utilizado nos antigos Teletipos, o DOS/Windows utiliza dois caracteres de controle para representar uma quebra de linha, um Carriage Return (CR = 0x0D) e um Line Feed (LF = 0x0A), porém sistemas Unix-Like perceberam que isso era um desperdício de 1 byte por linha e bastava um LF para representar uma nova linha.

Exemplo:

$ cat bacon.txt
Bacon Ipsum:

Bacon ipsum dolor sit amet salami
pork belly tail tongue pancetta,
pork loin tri-tip drumstick bresaola shankle.
$ file bacon_windows.txt bacon_linux.txt
bacon_windows.txt: ASCII text, with CRLF line terminators
bacon_linux.txt:   ASCII text
$ hexdump -C bacon_linux.txt
00000000  42 61 63 6f 6e 20 49 70  73 75 6d 3a <strong>0a 0a</strong> 42 61  |Bacon Ipsum:..Ba|
00000010  63 6f 6e 20 69 70 73 75  6d 20 64 6f 6c 6f 72 20  |con ipsum dolor |
00000020  73 69 74 20 61 6d 65 74  20 73 61 6c 61 6d 69 <strong>0a</strong>  |sit amet salami.|
00000030  70 6f 72 6b 20 62 65 6c  6c 79 20 74 61 69 6c 20  |pork belly tail |
00000040  74 6f 6e 67 75 65 20 70  61 6e 63 65 74 74 61 2c  |tongue pancetta,|
00000050  <strong>0a</strong> 70 6f 72 6b 20 6c 6f  69 6e 20 74 72 69 2d 74  |.pork loin tri-t|
00000060  69 70 20 64 72 75 6d 73  74 69 63 6b 20 62 72 65  |ip drumstick bre|
00000070  73 61 6f 6c 61 20 73 68  61 6e 6b 6c 65 2e <strong>0a</strong>     |saola shankle..|
0000007f
$ hexdump -C bacon_windows.txt
00000000  42 61 63 6f 6e 20 49 70  73 75 6d 3a <strong>0d 0a 0d 0a</strong>  |Bacon Ipsum:....|
00000010  42 61 63 6f 6e 20 69 70  73 75 6d 20 64 6f 6c 6f  |Bacon ipsum dolo|
00000020  72 20 73 69 74 20 61 6d  65 74 20 73 61 6c 61 6d  |r sit amet salam|
00000030  69 <strong>0d 0a</strong> 70 6f 72 6b 20  62 65 6c 6c 79 20 74 61  |i..pork belly ta|
00000040  69 6c 20 74 6f 6e 67 75  65 20 70 61 6e 63 65 74  |il tongue pancet|
00000050  74 61 2c <strong>0d 0a</strong> 70 6f 72  6b 20 6c 6f 69 6e 20 74  |ta,..pork loin t|
00000060  72 69 2d 74 69 70 20 64  72 75 6d 73 74 69 63 6b  |ri-tip drumstick|
00000070  20 62 72 65 73 61 6f 6c  61 20 73 68 61 6e 6b 6c  | bresaola shankl|
00000080  65 2e <strong>0d 0a</strong>                                       |e...|
00000084

Perceba que o arquivo criado no Windows contém a sequência 0d 0a nos lugares onde o arquivo criado no Linux aparece apenas 0a. É claro que isso ia trazer problemas de compatibilidade e dores de cabeça.

Apesar de bons editores conseguirem trabalhar com ambos os arquivos (no Notepad as linhas do bacon_linux.txt aparecerão todas concatenadas), arquivos que supostamente deveriam ser iguais aparecem como diferentes se usarmos ferramentas como o “diff”:

$ diff bacon_windows.txt bacon_linux.txt
1,5c1,5
< Bacon Ipsum:
<
< Bacon ipsum dolor sit amet salami
< pork belly tail tongue pancetta,
< pork loin tri-tip drumstick bresaola shankle.
---
> Bacon Ipsum:
>
> Bacon ipsum dolor sit amet salami
> pork belly tail tongue pancetta,
> pork loin tri-tip drumstick bresaola shankle.

Hoje coloquei alguns códigos feitos parte no Windows e parte no Linux em controle de versão e preferi padronizar tudo para usar apenas o LF. Aqui mostrarei como fiz a conversão automaticamente pelo Linux:

Vim

Duas formas:

1

  • Exibir CRLF como ^M: :e ++ff=unix.
  • Substituir todos os ^M por ^N: :s/\r/\r/.
  • Remover ^M só se ele estiver no fim da linha: :s/\r\+$//
  • Remover todos os ^M: :s/^M//

^M é digitado como ^V^M (ctrl+V ctrl+M).

2

  • Converter o formato do arquivo para unix: :setlocal fileformat=unix
  • Salvar: :w
  • Recarregar: :e

Converter vários arquivos

  • Assume formato DOS: :set ffs=dos.
  • Lista de arquivos a serem convertidos: :args *.c *.h.
  • Altera o formato de cada argumento: :argdo set ff=unix|w.

Outros comandos úteis: :set list e :set nobomb.

sed

sed, Stream EDitor, é um dos utilitários de linha de comando mais úteis para processar texto.

Ele trabalha linha a linha, então, se soubermos que o arquivo está no formato DOS podemos usar o sed para substituir os dois últimos caracteres (CRLF = /r/n) de cada linha por apenas LF (/n):

sed -i 's/.$//' arquivo.txt

Mas tome cuidado, pois se o arquivo já estiver no formato Unix, você vai acabar apagando o último caractere de cada linha.

O caminho contrário, converter um arquivo para o formato DOS, também pode ser feito com o GNU sed:

sed -i 's/$/\r/' arquivo.txt

Tofrodos

Se você não quiser se preocupar em verificar se o arquivo já segue o padrão Unix, uma alternativa ao sed é o Tofrodos. Se o arquivo já estiver convertido ele simplesmente deixa-o como está, isso é especialmente útil em scripts.

  1. Baixe e instale o Tofrodos, disponível no AUR. (Ou o dos2unix do community)

  2. Execute o seguinte comando na pasta que irá para o controle de versão (onde ^M é Ctrl+V + Ctrl+M):

    grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'
    

Este comando irá converter todos os CR+LF para LF em todos os arquivos da pasta atual e das subpastas.

Troque fromdos por todos para fazer a conversão contrária (LF para CR+LF).


Julio Batista Silva
Julio Batista Silva
Engenheiro de Dados

Eu sou um engenheiro de computação apaixonado por ciência, tecnologia, fotografia e idiomas. Atualmente trabalhando como Engenheiro de Dados na Alemanha.

comments powered by Disqus