如何在文本文件中查找行尾符?

461

我想在bash中使用某些东西来显示文件中的行尾,而不是解释它。该文件是从SSIS/SQL Server导出,由Linux机器读取进行处理。

  • 是否有任何在vilessmore等内部的选项?

  • 除了查看行尾之外,我还需要知道它是哪种类型的行尾(CRLFLF)。如何找到它?


1
一般提示:如果您知道可能使用哪个*nix/cygwin命令,您可以始终查看其man页以搜索可能为您提供所需功能的开关。例如,man less - David Rivers
12个回答

578
你可以使用 file 实用工具来判断文本文件的行尾类型。
Unix系统下:
$ file testfile1.txt
testfile.txt: ASCII text
"

“DOS”:

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

将"DOS"格式转换为Unix格式:

$ dos2unix testfile2.txt

将Unix格式转换为"DOS"格式:

$ unix2dos testfile1.txt

将已转换的文件再次转换不会产生任何影响,因此可以放心地运行(即无需先测试格式),尽管通常的免责声明仍然适用。


9
现在有些情况下它们被称为“fromdos”和“todos”,分别指代删除回车符和添加回车符(例如在Ubuntu 10.4+中)。 - Jess Chadwick
6
是的,但只有当你使用sudo apt-get install tofrodos显式安装了tofrodos软件包时才会生效 - 就像你必须运行sudo apt-get install dos2unix以获取dos2unixunix2dos一样。 - mklement0
实际上,dos2unix不能完成所有的工作,我认为https://dev59.com/BmAg5IYBdhLWcg3wOo79 给出了最好的答案。 - nathan
只是想插一句话,在Debian Jessie上,您可能需要安装“file”软件包才能首先使用“file”命令。 - Anglepoise
这对于像ssh密钥这样的文件不起作用,尽管它们是ASCII格式(使用file -bi进行验证),因为file会适当地命名它们,并且不会显示有关行结尾的信息;此外,OP要求打印行结尾,而不仅仅是它们的类型(LF或CRLF),因此@Alex Shelemin的答案更合适。 - Life5ign
显示剩余2条评论

301

Ubuntu 14.04:

使用简单的cat -e <filename>命令即可。

此命令将Unix换行符(\n或LF)显示为$,将Windows换行符(\r\n或CRLF)显示为^M$


22
也适用于OSX。不错的解决方案。对我很简单实用,而被接受的答案则不行。(注意:不是.txt文件) - dlsso
20
M$的显示是否是彩蛋/针对Windows的攻击? - Tom M
1
不能在Solaris上工作,但是手册说它应该可以工作。 - Zeus
1
@TomM 不是的。^M$ 中的脱字符 (^) 把它反转成了一个彩蛋,专门为微软追随者准备的。 - Bob Stein
2
我发现我必须使用 cat -vE <filename> 命令来查看文件中的 \r 字符(显示为 ^M),以及 \n 字符(显示为 $)。这是在 Linux 上使用 GNU cat 命令。 - xmnboy
显示剩余3条评论

147

vi中...

:set list 命令可以查看行尾标记。

:set nolist 命令可以返回普通模式。

虽然我认为在vi中无法看到\n\r\n,但是你可以查看文件类型(UNIX、DOS等)来推断它具有哪种行尾标记...

:set ff

另外,从bash中,你可以使用od -t c <filename>或者只使用od -c <filename>来显示回车符。


30
很遗憾,我认为vi无法显示那些特定的字符。您可以尝试使用od -c <文件名>命令,它可以显示\n或\r\n。 - Ryan Berger
3
在“值得一提”的类别中,您可以使用grep命令搜索DOS风格的CRLF,方法是发出grep --regex="^M"命令,其中^M表示CTRL+V CTRL+M。您可以通过sed命令替换这些内容来删除它们。这与dos2unix执行的基本相同。 - cowboydan
13
在Vim中,:set fileformat 命令会报告文件行尾是 unix 还是 dos。你可以通过命令 :set fileformat=unix 来改变行尾格式为Unix风格。 - Victor Zamanian
8
启动 vi/vim 时使用 -b 标志,然后使用 :set list 命令查看回车符 (^M) 和换行符 ($) 的结尾。 - Samuel
1
@RyanBerger - 看起来你少了一个-t。应该是 od -t c file/path,但还是谢谢你的新程序。运行得很好! - Eric Fossum
显示剩余5条评论

117
在Bash shell中,尝试使用cat -v <filename>命令。这将显示Windows文件的回车符。
(在Windows XP上,我通过Cygwin在rxvt中测试成功。)
编辑说明:cat -v\r(CR)字符可视化为^M。因此,换行符\r\n序列将显示为每个输出行末尾的^Mcat -e还将可视化\n$。(cat -et还将标签字符可视化为^I。)

3
尝试运行命令echo -e 'abc\ndef\r\n' | cat -v,你会看到在 "def" 后面出现一个 ^M 字符。请注意,该命令的功能不受影响,它仅仅是表示了回车符的存在。 - Dennis Williamson
我想查看文件是否有^M(Windows/DOS EOL),只有cat -v才能显示。对此点赞+1。 - Ali
2
^M = DOS/Windows风格 - Mercury
1
因此,行尾的 \r\n 序列将显示为 ^M$。 - Shayan

44

尝试使用file,然后是file -k,最后是dos2unix -ih

file通常就足够了。但对于复杂的情况,请尝试使用file -kdos2unix -ih

详细信息如下。


尝试使用file -k

简短版:file -k somefile.txt将告诉您行终止符:

  • 对于 DOS/Windows 行终止符,它将输出 with CRLF line terminators
  • 对于 MAC 行终止符,它将输出 with CR line terminators
  • 对于 Linux/Unix 的 "LF" 行终止符,它将只输出 text。(所以如果它没有明确提到任何类型的line terminators,那么这意味着:"LF行终止符"。)

对于额外奇怪的情况:当您有混合的行终止符时:

  • $ echo -ne '1\n2\r\n3\r' | file -k -
    /dev/stdin: ASCII text, with CRLF, CR, LF line terminators

详细版本请见下文。


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

我有时需要检查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

哦,它没有告诉我行终止符。而且我已经知道那些是证书文件了,我不需要“文件”来告诉我。

一些网络设备对其证书文件的编码方式非常挑剔,这就是为什么我需要知道的原因。

你还可以尝试使用dos2unix命令,并加上--info开关,像这样:

$ 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 期望一个“常规”文本文件的方式。

(如果你想记忆我的口诀:“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  

很好。现在所有证书都有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

又一个“实际”的时刻:头格式真的很容易记住:这里有两个助记符:

  1. 它是“愚蠢的”(从左到右:d代表Dos,u代表Unix,m代表Mac,b代表BOM)。
  2. 而且:“DUM”只是D、U和M的字母顺序。

进一步阅读


1
在MinTTY中的Windows上,它会生成类似于“Accounts.java:Java源代码,ASCII文本\012-”的输出。 - chill appreciator
很有趣。我读到了一些关于一个叫做“igncr”的选项的奇怪事情,你所说的听起来像是那个问题。但是我无法重现你所描述的情况。(我在Git-for-Windows中使用的mintty内部的Bash中尝试了一下,“git version 2.24.0.windows.1”)。 - StackzOfZtuff
嗯,我也在带有git-for-windows的mintty中尝试了file -k Accounts.java,但我的版本是git version 2.21.0.windows.1 - chill appreciator
对我来说可行的解决方案是 cat -e file_to_test - chill appreciator

22
展示 CR 为 ^M 在 less 中使用 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.

2
请澄清您的回答。 - adao7000

8
你可以使用xxd来显示文件的十六进制转储,然后搜索"0d0a"或"0a"字符。
你可以像@warriorpostman建议的那样使用cat -v <filename>

1
它适用于我使用的cat v 8.23。Unix行结尾不会打印任何额外的信息,但是DOS行结尾会打印一个“^M”。 - Rich
这一定是我在8.21版本中遇到的问题,因为我正在使用Unix换行符。 - neanderslob

5

您可以使用命令todos文件名将文本转换为DOS格式,使用fromdos文件名将文本转换为UNIX格式。在Ubuntu上安装该软件包,输入sudo apt-get install tofrodos


5
您可以使用vim -b filename进入二进制模式编辑文件,这将显示^M字符表示回车,并且换行符表示有LF存在,这表明Windows使用CRLF作为行末标识。其中LF表示\n,CR表示\r。请注意,当您使用-b选项时,默认情况下文件将总是以UNIX模式进行编辑,并在状态行中显示[unix],这意味着如果您添加新行,它们将以LF结尾,而不是CRLF。如果您在具有CRLF行尾的文件上使用普通的vim而没有使用-b,则应在状态行中看到[dos],并且插入行将以CRLF作为行末。对于fileformats设置,vim文档解释了复杂性。此外,我没有足够的积分来评论Notepad++答案,但如果您在Windows上使用Notepad ++,请使用View / Show Symbol / Show End of Line菜单来显示CR和LF。在这种情况下,LF显示出来,而对于vim,LF则表示为新行。

1
我将输出转储到文本文件中,然后在记事本++中打开它,然后点击显示所有字符按钮。这并不十分优雅,但它有效。

3
这个问题被标记为Linux,我认为Notepad++不适用于Linux系统。但是它应该可以在Windows系统上使用。 - Rick Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接