Como descobrir terminações de linha em um arquivo de texto?

304

Estou tentando usar algo no bash para me mostrar as terminações de linha em um arquivo impresso em vez de interpretado. O arquivo é um despejo do SSIS / SQL Server sendo lido por uma máquina Linux para processamento.

  • Há algum interruptores dentro vi, less, more, etc?

  • Além de ver os finais de linha, preciso saber que tipo de final de linha é ( CRLFou LF). Como faço para descobrir isso?

Marco Ceppi
fonte
1
Dica geral: Se você tem uma idéia de qual comando * nix / cygwin pode usar, sempre pode ver sua página de manual para procurar opções que possam fornecer a funcionalidade necessária. Por exemplo man less,.
David Rivers

Respostas:

421

Você pode usar o fileutilitário para fornecer uma indicação do tipo de final de linha.

Unix:

$ file testfile1.txt
testfile.txt: ASCII text

"DOS":

$ file testfile2.txt
testfile2.txt: ASCII text, with CRLF line terminators

Para converter de "DOS" para Unix:

$ dos2unix testfile2.txt

Para converter de Unix para "DOS":

$ unix2dos testfile1.txt

A conversão de um arquivo já convertido não tem efeito, portanto é seguro executar cegamente (ou seja, sem testar o formato primeiro), embora as isenções de responsabilidade usuais se apliquem, como sempre.

Pausado até novo aviso.
fonte
9
Estas são agora, por vezes, chamado "fromdos" e "todos", respectivamente (como é o caso no Ubuntu 10.4+)
Jess Chadwick
3
@JessChadwick: Sim, mas somente se você instalar explicitamente o tofrodospacote sudo apt-get install tofrodos- assim como você precisaria executar sudo apt-get install dos2unixpara obter dos2unixe unix2dos.
mklement0
Actully dos2unix não pode fazer todo o trabalho, eu acho stackoverflow.com/questions/23828554/dos2unix-doesnt-convert-m dá melhor resposta
Nathan
@nathan: O que dos2unixfalha em? O PO dessa pergunta apenas descreve vagamente a questão.
Pausado até novo aviso.
O comando @DennisWilliamson file antes e depois do comando dos2unix obteve a mesma saída: xxx.c C source, texto ASCII, com terminadores de linha CR e LF. Eu encontrei este arquivo c tem ^ M no meio da linha que gosta xxxxxxx ^ M xxxxxxx
Nathan
127

Em vi...

:set list para ver finais de linha.

:set nolist para voltar ao normal.

Enquanto eu não acho que você pode ver \nou \r\nno vi, você pode ver que tipo de arquivo é (UNIX, DOS, etc.) para inferir que as terminações de linha que tem ...

:set ff

Como alternativa, bashvocê pode usar od -t c <filename>ou apenas od -c <filename>para exibir os retornos.

Ryan Berger
fonte
26
Infelizmente, não acho que o vi possa mostrar esses caracteres específicos. Você pode tentar od -c <filename>, que acredito que será exibido \ n ou \ r \ n.
Ryan Berger
3
Na categoria "para o que vale a pena", você pode grep para o estilo Dos CRLF emitindo grep --regex = "^ M" onde ^ M é CTRL + V CTRL + M. Você pode removê-los, substituindo-os por um comando sed. Isso faz essencialmente a mesma coisa que dos2unix
cowboydan
11
No vim: :set fileformatinformará em qual unixou o dosvim acha que estão as terminações de linha do arquivo. Você pode alterá-lo :set fileformat=unix.
Victor Zamanian
5
Use o sinalizador -b ao iniciar o vi / vim e, em seguida, use: set list para ver as terminações CR (^ M) e LF ($).
Samuel
1
@RyanBerger - Parece que você está perdendo um t. Deveria ser od -t c file/path, mas obrigado pelo novo programa. Trabalhou muito bem!
Eric Fossum
113

Ubuntu 14.04:

cat -e <filename>Trabalhos simples muito bem.

Isso exibe finais de linha Unix ( \nou LF) como $e finais de linha do Windows ( \r\nou CRLF) como ^M$.

Alexander Shelemin
fonte
7
Também funciona no OSX. Boa solução. Simples e funcionou para mim, enquanto a resposta aceita não. (Nota: não era um .txtarquivo)
dlsso
4
é a exibição de M $ um easteregg / windows bashing?
Tom M
Não funciona com Solaris, mas o homem diz tthat deveria ter trabalhado
Zeus
101

No shell bash, tente cat -v <filename>. Isso deve exibir retornos de carro para arquivos do Windows.

(Isso funcionou para mim no rxvt via Cygwin no Windows XP).

Nota do editor: cat -vvisualiza \rcaracteres (CR). como ^M. Assim, as \r\nseqüências de final de linha serão exibidas ^Mno final de cada linha de saída. cat -eirá visualizar adicionalmente \n, nomeadamente como $. ( cat -etvisualiza adicionalmente os caracteres das guias. como ^I.)

guerreiro
fonte
3
@ ChrisK: Tente echo -e 'abc\ndef\r\n' | cat -ve você deve ver um ^Mapós o "def".
Pausado até novo aviso.
Eu queria ver se o arquivo tem ^ M (Windows / DOS EOL) e apenas cat -v me mostrou isso. +1 para isso
Ali
1
^ M = estilo DOS / Windows
Mercury
correção: Assim, as seqüências \ r \ n de final de linha serão exibidas como ^ M $
Shayan
19

Para mostrar CR como ^Mmenos uso less -uou digitar -umenos uma vez, está aberto.

man less diz:

-u or --underline-special

      Causes backspaces and carriage returns to be treated  as  print-
      able  characters;  that  is,  they are sent to the terminal when
      they appear in the input.
P. Kucerak
fonte
1
Por favor, esclareça sua resposta.
adao7000
12

Tente fileentão file -kentãodos2unix -ih

filenormalmente será suficiente. Mas, para casos difíceis, tente file -kou dosunix -ih.

Detalhes abaixo.


Experimentar file -k

Versão curta: file -k somefile.txt vou te dizer.

  • Ele produzirá with CRLF line endingspara terminações de linha do DOS / Windows.
  • Ele produzirá with LF line endingspara terminações de linha MAC.
  • E para a linha "CR" do Linux / Unix, ela apenas produzirá text. (Portanto, se ele não mencionar explicitamente nenhum tipo line endings, isso significa implicitamente: "finais de linha CR" .)

Versão longa, veja abaixo.


Exemplo do mundo real: codificação de certificado

Às vezes, tenho que verificar isso em busca de arquivos de certificado PEM.

O problema com o regular fileé o seguinte: às vezes, ele tenta ser muito inteligente / muito específico.

Vamos tentar um pequeno teste: eu tenho alguns arquivos. E um desses arquivos possui finais de linha diferentes. Qual?

(A propósito: é assim que um dos meus diretórios típicos de "trabalho de certificado" se parece.)

Vamos tentar regularmente file:

$ file -- *
0.example.end.cer:         PEM certificate
0.example.end.key:         PEM RSA private key
1.example.int.cer:         PEM certificate
2.example.root.cer:        PEM certificate
example.opensslconfig.ini: ASCII text
example.req:               PEM certificate request

Hã. Não está me dizendo os finais da linha. E eu já sabia que eram arquivos cert. Eu não precisava de "arquivo" para me dizer isso.

O que mais você pode tentar?

Você pode tentar dos2unixcom a --infoopção assim:

$ dos2unix --info -- *
  37       0       0  no_bom    text    0.example.end.cer
   0      27       0  no_bom    text    0.example.end.key
   0      28       0  no_bom    text    1.example.int.cer
   0      25       0  no_bom    text    2.example.root.cer
   0      35       0  no_bom    text    example.opensslconfig.ini
   0      19       0  no_bom    text    example.req

Então isso diz a você que: sim, "0.example.end.cer" deve ser o homem estranho. Mas que tipo de finais de linha existem? Do que você sabe o formato de saída dos2unix de cor? (Eu não.)

Mas, felizmente, existe a opção --keep-going(ou -kabreviada) em file:

$ file --keep-going -- *
0.example.end.cer:         PEM certificate\012- , ASCII text, with CRLF line terminators\012- data
0.example.end.key:         PEM RSA private key\012- , ASCII text\012- data
1.example.int.cer:         PEM certificate\012- , ASCII text\012- data
2.example.root.cer:        PEM certificate\012- , ASCII text\012- data
example.opensslconfig.ini: ASCII text\012- data
example.req:               PEM certificate request\012- , ASCII text\012- data

Excelente! Agora sabemos que nosso arquivo ímpar possui CRLFterminações de linha DOS ( ). (E os outros arquivos têm LFfinais de linha Unix ( ). Isso não está explícito nesta saída. Está implícito. É exatamente assim que se fileespera que um arquivo de texto "regular" seja.)

(Se você quiser compartilhar meu mnemônico: "L" é para "Linux" e "LF".)

Agora vamos converter o culpado e tentar novamente:

$ dos2unix -- 0.example.end.cer

$ file --keep-going -- *
0.example.end.cer:         PEM certificate\012- , ASCII text\012- data
0.example.end.key:         PEM RSA private key\012- , ASCII text\012- data
1.example.int.cer:         PEM certificate\012- , ASCII text\012- data
2.example.root.cer:        PEM certificate\012- , ASCII text\012- data
example.opensslconfig.ini: ASCII text\012- data
example.req:               PEM certificate request\012- , ASCII text\012- data  

Boa. Agora todos os certificados têm finais de linha Unix.

Experimentar dos2unix -ih

Eu não sabia disso quando estava escrevendo o exemplo acima, mas:

Na verdade, acontece que o dos2unix fornecerá uma linha de cabeçalho se você usar -ih(abreviação de --info=h) assim:

$ dos2unix -ih -- *
 DOS    UNIX     MAC  BOM       TXTBIN  FILE
   0      37       0  no_bom    text    0.example.end.cer
   0      27       0  no_bom    text    0.example.end.key
   0      28       0  no_bom    text    1.example.int.cer
   0      25       0  no_bom    text    2.example.root.cer
   0      35       0  no_bom    text    example.opensslconfig.ini
   0      19       0  no_bom    text    example.req

E outro momento "realmente": o formato do cabeçalho é realmente fácil de lembrar: Aqui estão duas mnemônicas:

  1. É DUMB (da esquerda para a direita: d para Dos, u para Unix, m para Mac, b para BOM).
  2. E também: "DUM" é apenas a ordem alfabética de D, U e M.

Leitura adicional

StackzOfZtuff
fonte
1
Ele gera saída como: Accounts.java: Java source, ASCII text\012-no Windows no MinTTY
stand alone
@ standalone: ​​interessante. Eu li coisas estranhas sobre uma opção chamada "igncr" - e o que você está dizendo soa assim. Mas não pode reproduzir o que você descreve. (Eu tentei dentro do Bash dentro do mintty que vem com o Git-for-Windows, "git versão 2.24.0.windows.1".))
StackzOfZtuff
Hm, eu tentei file -k Accounts.javadentro do mintty que vem com o git-for-windows também, mas minha versão égit version 2.21.0.windows.1
stand alone
Solução de trabalho para mim écat -e file_to_test
stand alone
9

Você pode usar xxdpara mostrar um despejo hexadecimal do arquivo e procurar caracteres "0d0a" ou "0a".

Você pode usar cat -v <filename>como @warriorpostman sugere.

Rico
fonte
1
Funciona para mim com o gato v 8.23. As terminações de linha Unix não imprimirão nenhuma informação extra, mas as finais de linha do DOS imprimirão um "^ M".
Rich
Deve ser o que estou encontrando com a 8.21, considerando o fato de estar usando terminações de linha unix.
Neanderslob
5

Você pode usar o comando todos filenamepara converter em finais do DOS e fromdos filenameem finais da linha UNIX. Para instalar o pacote no Ubuntu, digite sudo apt-get install tofrodos.

Zorayr
fonte
5

Você pode usar vim -b filenamepara editar um arquivo no modo binário, que mostrará ^ M caracteres para retorno de carro e uma nova linha indicará a presença de LF, indicando as terminações da linha CRLF do Windows. Por LF eu quero dizer \ne por CR eu quero dizer \r. Observe que, quando você usa a opção -b, o arquivo sempre será editado no modo UNIX por padrão, conforme indicado [unix]na linha de status, o que significa que, se você adicionar novas linhas, elas terminarão com LF, não com CRLF. Se você usar o vim normal sem -b em um arquivo com terminações de linhas CRLF, deverá ver [dos]a linha de status e as linhas inseridas terão CRLF como final de linha. A documentação do vim para fileformatsconfiguração explica as complexidades.

Além disso, não tenho pontos suficientes para comentar a resposta do Notepad ++, mas se você usar o Notepad ++ no Windows, use o menu Exibir / Mostrar símbolo / Mostrar fim da linha para exibir CR e LF. Neste caso, LF é mostrado, enquanto que para vim o LF é indicado por uma nova linha.

smalers
fonte
0

Eu despejo minha saída em um arquivo de texto. Em seguida, abro-o no bloco de notas ++ e clico no botão Mostrar todos os caracteres. Não é muito elegante, mas funciona.

Diego
fonte
3
Esta questão está etiquetada como Linux e não acho que o bloco de notas ++ seja para linux. Isso deve funcionar para o Windows.
Rick Smith
0

Vim - sempre mostre as novas linhas do Windows como ^M

Se você preferir sempre ver as novas linhas do Windows no vim render as ^M, você pode adicionar esta linha ao seu .vimrc:

set ffs=unix

Isso fará com que o vim interprete todos os arquivos que você abrir como um arquivo unix. Como os arquivos unix têm \ncomo caractere de nova linha, um arquivo do Windows com um caractere de nova linha \r\nainda será renderizado corretamente (graças ao \n), mas terá ^Mno final do arquivo (que é como o vim renderiza o \rcaractere).


Vim - às vezes mostra novas linhas do Windows

Se você preferir defini-lo por arquivo, use-o :e ++ff=unixao editar um determinado arquivo.


Vim - sempre mostra o tipo de arquivo ( unixvs dos)

Se você quer a linha de fundo do vim para exibir sempre o que você está editando filetype (e você não forçou definir o tipo de arquivo para unix), você pode adicionar à sua statuslinecom
set statusline+=\ %{&fileencoding?&fileencoding:&encoding}.

Minha linha de status completa é fornecida abaixo. Basta adicioná-lo ao seu .vimrc.

" Make statusline stay, otherwise alerts will hide it
set laststatus=2
set statusline=
set statusline+=%#PmenuSel#
set statusline+=%#LineNr#
" This says 'show filename and parent dir'
set statusline+=%{expand('%:p:h:t')}/%t
" This says 'show filename as would be read from the cwd'
" set statusline+=\ %f
set statusline+=%m\
set statusline+=%=
set statusline+=%#CursorColumn#
set statusline+=\ %y
set statusline+=\ %{&fileencoding?&fileencoding:&encoding}
set statusline+=\[%{&fileformat}\]
set statusline+=\ %p%%
set statusline+=\ %l:%c
set statusline+=\ 

Vai render como

.vim/vimrc\                                    [vim] utf-8[unix] 77% 315:6

na parte inferior do seu arquivo


Vim - às vezes mostra o tipo de arquivo ( unixvs dos)

Se você quiser apenas ver que tipo de arquivo possui, poderá usar :set fileformat(isso não funcionará se você forçar a definição do tipo de arquivo). Ele retornará unixpara arquivos unix e dospara Windows.

jeremysprofile
fonte