为什么文本文件以换行符结束?

我假设这里的每个人都熟悉所有文本文件应该以换行符结尾的格言。 我已经知道这个“规则”多年了,但我总是想知道 - 为什么?


因为这就是POSIX标准定义一条线的方式

3.206行零或多个非<新行>字符以及终止的<新行>字符的序列。

因此,不以换行符结尾的行不被视为实际行。 这就是为什么有些程序在处理文件的最后一行时遇到问题,如果它不是换行符终止。

在终端仿真器上工作时,本指南至少有一个硬件优势:所有的Unix工具都希望遵循这个惯例并且能够使用它。 例如,当与cat连接文件时,由换行符终止的文件将具有不同于不具有以下特征的文件:

$ more a.txt
foo$ more b.txt
bar
$ more c.txt
baz
$ cat *.txt
foobar
baz

而且,如前面的例子所示,当在命令行上显示文件时(例如,通过more ),以换行符结尾的文件会导致正确的显示。 不正确地终止的文件可能会出现乱码(第二行)。

为了保持一致性,遵循这条规则非常有帮助 - 否则在处理默认的Unix工具时会招致额外的工作。

现在,在不符合POSIX标准的系统(现在主要是Windows)上,重点是没有意义的:文件通常不会以换行符结尾,而行的(非正式)定义可能是“文本被换行符分隔” (注意重点)。 这完全有效。 但是,对于结构化数据(例如编程代码),它使解析最小化更复杂:通常意味着解析器必须被重写。 如果解析器最初是用POSIX定义编写的,那么修改令牌流而不是解析器可能更容易 - 换句话说,在输入的末尾添加“artificial newline”标记。


每行应以换行符结尾,包括最后一行。 如果文件的最后一行不是换行符终止,某些程序会遇到问题。

GCC警告说,这不是因为它无法处理文件,而是因为它必须作为标准的一部分。

C语言标准说,一个非空的源文件应以换行符结尾,该字符不能立即以反斜杠字符开头。

由于这是“必须”条款,因此我们必须发布违反此规则的诊断信息。

这是ANSI C 1989标准的2.1.1.2节。 ISO C 1999标准的第5.1.1.2节(也可能是ISO C 1990标准)。

参考:GCC / GNU邮件存档。


这个答案是一个技术答案而不是意见的尝试。

如果我们想成为POSIX纯粹主义者,我们将一条线定义为:

一系列零个或多个非<新行>字符加上终止的<新行>字符。

来源:http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206

不完整的行如下所示:

文件末尾的一个或多个非<新行>字符序列。

资料来源:http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195

一个文本文件为:

包含组织为零或多行的字符的文件。 这些行不包含NUL字符,并且任何长度都不能超过{LINE_MAX}个字节,包括<newline>字符。 尽管POSIX.1-2008没有区分文本文件和二进制文件(请参阅ISO C标准),但许多实用程序仅在文本文件上操作时才会产生可预测或有意义的输出。 具有此类限制的标准实用程序始终在STDIN或INPUT FILES部分中指定“文本文件”。

资料来源:http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397

一个字符串如下:

由第一个空字节终止的连续字节序列。

来源:http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396

从这里,我们可以推导出,我们唯一可能遇到的任何类型的问题是,如果我们将文件行或文件的概念作为文本文件处理(即文本文件是零组织或更多的行,我们知道的一行必须以<newline>结尾)。

例如: wc -l filename

wc的手册中我们看到:

一行被定义为一个由<换行符>字符分隔的字符串。

对JavaScript,HTML和CSS文件有什么影响,然后是文本文件?

在浏览器,现代IDE和其他前端应用程序中,在EOF上跳过EOL没有任何问题。 应用程序将正确解析文件。 因为并非所有操作系统都符合POSIX标准,所以对于非操作系统工具(例如浏览器)根据POSIX标准(或任何操作系统级标准)处理文件是不切实际的。

因此,我们可以相对确信EOF在应用程序级别上几乎没有负面影响 - 无论它是否在UNIX操作系统上运行。

在这一点上,我们可以自信地说,在客户端处理JS,HTML和CSS时,在EOF上跳过EOL是安全的。 实际上,我们可以声明缩小这些文件中不包含<newline>的文件是安全的。

我们可以进一步说,就NodeJS而言,它也不能遵守POSIX标准,因为它可以在非POSIX兼容环境中运行。

那么我们留下了什么? 系统级工具。

这意味着唯一可能出现的问题是使用努力将其功能与POSIX的语义相结合的工具(例如wc所示的行的定义)。

即便如此,并非所有的shell都会自动遵守POSIX。 Bash例如不默认为POSIX行为。 有一个开关来启用它: POSIXLY_CORRECT

关于EOL的价值的思考<newline>:http://www.rfc-editor.org/EOLstory.txt

留在模具轨道上,为了所有的实际意图和目的,让我们考虑一下:

我们来处理一个没有EOL的文件。 在撰写本文时,本例中的文件是一个没有EOL的缩小JavaScript。

curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o x.js
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o y.js

$ cat x.js y.js > z.js

-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 x.js
-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 y.js
-rw-r--r--  1 milanadamovsky  15810 Aug 14 23:18 z.js

请注意, cat文件大小恰好是其各个部分的总和。 如果JavaScript文件的连接是JS文件的关注点,则更合适的关注点是使用分号开始每个JavaScript文件。

正如其他人在这个线程中提到的那样:如果你想要cat两个文件,其输出只能是一行而不是两行? 换句话说, cat做它应该做的事情。

catman只提到阅读输入到EOF,而不是<newline>。 请注意, cat-n开关也会将非终止线(或不完整的线)打印出一行 - 即计数从1开始(根据man

-n从1开始对输出行进行编号。

现在我们已经理解了POSIX如何定义一条线,这种行为变得模糊不清或者确实不符合规定。

了解给定工具的目的和合规性将有助于确定使用EOL结束文件的重要性。 在C,C ++,Java(JAR)等...一些标准将决定新的有效性 - 没有这样的JS,HTML,CSS标准。

例如,不用wc -l filename就可以awk '{x++}END{ print x}' filename ,并确信任务的成功不会受到我们可能想要处理的文件的危害,我们没有写(例如第三方库,比如我们curl的缩小的JS) - 除非我们的意图是在POSIX合规意义上真正地计数行。

结论

对于某些文本文件(如JS,HTML和CSS),在EOF中跳过EOL将产生负面影响 - 如果有的话,实际使用情况很少。 如果我们依赖<newline>存在,我们只会将我们工具的可靠性限制在我们编写的文件中,并将自己置于由第三方文件引入的潜在错误之中。

故事的道德:在EOF上没有依赖EOL的弱点的工程师工具。

随意发布使用案例,因为它们适用于JS,HTML和CSS,我们可以检查如何跳过EOL会产生不利影响。

链接地址: http://www.djcxy.com/p/13519.html

上一篇: Why should text files end with a newline?

下一篇: How can I remove (chomp) a trailing newline in Python?