如何找出文本文件中的行结束符?

我试图使用bash中的一些东西向我显示打印而不是解释的文件中的行结束符。该文件是从SSIS/SQL Server中转储的,由Linux机器读入以进行处理。

  • vilessmore等中是否存在任何开关?

  • 除了看到行结束符,我还需要知道它是什么类型的行结束符(CRLFLF)。我怎么知道呢?

459102 次浏览

vi

:set list查看行结束符。

:set nolist恢复正常。

虽然我不认为你可以在vi中看到\n\r\n,但你可以看到它是哪种类型的文件(UNIX, DOS等)来推断它有哪些行结束符……

:set ff

或者,在bash中,你可以使用od -t c <filename>od -c <filename>来显示返回值。

在bash shell中,尝试cat -v <filename>。这将显示windows文件的回车。

(这适用于我在Windows XP上通过Cygwin的rxvt)。

编者注:cat -v显示\r (CR)字符。^M。因此,行结束的\r\n序列将在每个输出行的末尾显示为^Mcat -e将额外可视化\n,即$。(cat -et将额外可视化制表符。^I。)

可以使用file实用程序来指示行结束符的类型。

Unix:

$ file testfile1.txt
testfile.txt: ASCII text

“做”:

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

将“DOS”转换为Unix:

$ dos2unix testfile2.txt

从Unix转换到DOS:

$ unix2dos testfile1.txt

转换一个已经转换的文件没有效果,所以盲目运行是安全的(即不先测试格式),尽管通常的免责声明适用,一如既往。

可以使用命令todos filename转换为DOS结尾,使用命令fromdos filename转换为UNIX行结尾。要在Ubuntu上安装软件包,输入sudo apt-get install tofrodos

你可以使用xxd来显示文件的十六进制转储,并遍历“0d0a”或“0a”字符。

你可以像@warriorpostman建议的那样使用cat -v <filename>

要在less中显示CR为^M,请使用less -u或在less打开时键入-u

man less说:

-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.

我将输出转储到一个文本文件中。然后我在notepad++中打开它,然后单击显示所有字符按钮。不是很优雅,但是很好用。

Ubuntu 14.04:

简单的cat -e <filename>工作得很好。

这将Unix的行结束符(\n或LF)显示为$, Windows的行结束符(\r\n或CRLF)显示为^M$

你可以使用vim -b filename在二进制模式下编辑文件,它将显示^M个字符作为回车符,新行表示LF,表示Windows CRLF行结束符。这里的LF指的是\n, CR指的是\r。注意,当您使用-b选项时,默认情况下,文件将始终在UNIX模式下编辑,如状态行中的[unix]所示,这意味着如果您添加新行,它们将以LF结束,而不是CRLF。如果你对一个带有CRLF行结束符的文件使用不带-b的普通vim,你应该看到[dos]显示在状态行中,插入的行将以CRLF作为行结束符。fileformats设置的vim文档解释了复杂性。

另外,我没有足够的点来评论notepad++的答案,但如果你在Windows上使用notepad++,使用查看/显示符号/显示行结束菜单来显示CR和LF。在本例中显示LF,而对于vim, LF由新行表示。

尝试file,然后file -k,然后dos2unix -ih

file通常就足够了。但对于棘手的情况,请尝试file -kdosunix -ih

下面的细节。


尝试file -k

短版: file -k somefile.txt会告诉你。

  • 它将为DOS/Windows行结束符输出with CRLF line endings
  • 它将为MAC行结束符输出with CR line endings
  • 它只会输出text for Linux/Unix "LF"线的结局。(因此,如果它没有显式地提到任何类型的line endings,则这意味着:“LF行尾”;。)

长版本见下文。


真实世界的例子:证书编码

我有时需要检查PEM证书文件。

常规file的问题是:有时它试图太聪明/太具体。

让我们做个小测试:我有一些文件。其中一个文件有不同的行尾。哪一个?

(顺便说一下:这是我的一个典型的“证书作品”。目录是这样的。)

让我们试试常规的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

嗯。它没有告诉我行将结束。我已经知道,那些是证书文件。我不需要“文件”;告诉我。

一些网络设备对它们的证书文件的编码方式非常非常挑剔。所以我才需要知道。

你还能尝试什么?

你可以像这样用--info开关尝试dos2unix:

$ 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

这就告诉你,是的,";0。example。end。cer ";一定是异类。但是行尾是什么样的呢?能记住dos2unix输出格式吗?(我不喜欢。)

但幸运的是,在file中有--keep-going(或简称-k)选项:

$ 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

太好了!现在我们知道奇数文件有DOS (CRLF)行结束符。(其他文件有Unix (LF)行结束符。这在输出中不是显式的。它是隐式的。这就像file期待一个"regular"文本文件。)

(如果你想分享我的记忆:"L"是“linux”;和"LF")

现在让我们转换罪魁祸首,再试一次:

$ 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

很好。现在所有的cert都有Unix行结束符。

尝试dos2unix -ih

当我写上面的例子时,我并不知道这一点,但是:

实际上,如果你像这样使用-ih (--info=h的缩写),dos2unix会给你一个标题行:

$ 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

另一个"actually"moment:标题的格式真的很容易记住:这里有两个助记符:

  1. 它是DUMB(从左到右:d代表Dos, u代表Unix, m代表Mac, b代表BOM)。
  2. 还有:"DUM"就是D U M的字母顺序

进一步的阅读

Vim -总是显示Windows换行符为^M

如果你喜欢在vim渲染中总是看到Windows换行符为^M,你可以将这一行添加到你的.vimrc:

set ffs=unix

这将使vim将您打开的每个文件解释为unix文件。由于unix文件以\n作为换行符,具有\r\n换行符的windows文件仍将正确呈现(多亏了\n),但在文件的末尾将有^M(这就是vim呈现\r字符的方式)。


Vim -有时显示Windows换行符

如果你更喜欢在每个文件的基础上设置它,你可以在编辑给定文件时使用:e ++ff=unix


Vim -始终显示文件类型(unix vs dos)

如果你想让vim的底线始终显示你正在编辑的文件类型(并且你没有强制将文件类型设置为unix),你可以用
添加到你的statusline set statusline+=\ %{&fileencoding?&fileencoding:&encoding} . < / p >

我的完整状态线如下所示。只要把它添加到你的.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+=\

它会渲染成

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

在你文件的底部


Vim -有时显示文件类型(unix vs dos)

如果你只是想知道你有什么类型的文件,你可以使用:set fileformat(如果你强制设置文件类型,这将不起作用)。它将返回unix文件的unix和Windows文件的dos