我想这里的每个人都熟悉这句谚语,即所有文本文件都应该以换行符结尾。我已经知道这个“规则”很多年了,但我一直在想——为什么?


当前回答

这源于使用简单终端的早期。换行符用于触发传输数据的“刷新”。

今天,不再需要换行符。当然,如果没有换行符,许多应用程序仍然存在问题,但我认为这是这些应用程序中的一个错误。

然而,如果你有一个需要换行符的文本文件格式,那么你可以得到非常便宜的简单数据验证:如果文件以结尾没有换行符的行结尾,那么你就知道文件已损坏。每行只有一个额外的字节,您可以高精度地检测损坏的文件,几乎不需要CPU时间。

其他回答

很可能只是一些解析代码希望它在那里。

我不确定我是否会认为这是一条“规则”,而且这肯定不是我虔诚地遵守的。最明智的代码将知道如何逐行解析文本(包括编码)(任何行结尾的选择),最后一行是否有换行符。

的确,如果你以一条新的线结束:EOL和EOF之间(理论上)是否有一条空的最终线?一个值得思考的。。。

天啊,这是个人风格和观点的问题。

在过去,我没有写那句新语。保存的字符意味着14.4K调制解调器的速度更快。

稍后,我放置了换行符,以便使用shift+向下箭头更容易选择最后一行。

一个单独的用例:当文本文件受版本控制时,提交卫生。

如果将内容添加到文件末尾,则先前是最后一行的行将被编辑为包含换行符。这意味着,打开文件以了解该行最后一次编辑的时间将显示换行符添加,而不是您实际希望看到的提交。

(该示例特定于git,但同样的方法也适用于其他版本控制系统。)

基本上,如果没有得到最终EOL EOF,许多程序将无法正确处理文件。

GCC警告您这一点,因为它是C标准的一部分。(第5.1.1.2节明显)

“文件末尾没有换行符”编译器警告

因为POSIX标准就是这样定义一行的:

3.206线路一个由零个或多个非<换行符>字符加上一个终止<换行符]字符组成的序列。

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

在使用终端仿真器时,该指南至少有一个硬优势:所有Unix工具都希望使用此约定并使用它。例如,当使用cat连接文件时,以换行符结尾的文件将具有不同于不使用的效果:

$ more a.txt
foo
$ more b.txt
bar$ more c.txt
baz
$ cat {a,b,c}.txt
foo
barbaz

而且,如前一个示例所示,当在命令行上显示文件时(例如,通过more),换行的文件会导致正确的显示。未正确终止的文件可能会乱码(第二行)。

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


换一种方式思考:如果行没有以换行符结尾,那么让cat之类的命令变得有用就要困难得多了:如何创建一个连接文件的命令,以便

它将每个文件的开头放在一个新行上,这是您95%的时间所希望的;但是它允许合并两个文件的最后一行和第一行,就像上面的例子中的b.txt和c.txt?

当然,这是可以解决的,但您需要使cat的使用更加复杂(通过添加位置命令行参数,例如cat a.txt--no newline b.txt c.txt),现在命令而不是每个单独的文件控制它如何与其他文件粘贴在一起。这几乎肯定不方便。

……或者您需要引入一个特殊的哨兵字符来标记应该继续而不是终止的行。好吧,现在您遇到了与POSIX相同的情况,除了反转(行继续而不是行终止字符)。


现在,在非POSIX兼容的系统(现在主要是Windows)上,问题是没有意义的:文件通常不会以换行符结尾,例如,行的(非正式)定义可能是“用换行符分隔的文本”(注意重点)。这是完全有效的。然而,对于结构化数据(例如编程代码),它使解析更加复杂:这通常意味着必须重写解析器。如果解析器最初是在考虑POSIX定义的情况下编写的,那么修改令牌流可能比修改解析器更容易——换句话说,在输入末尾添加一个“人造换行符”令牌。