为什么建议在源文件的末尾使用空行?

一些代码风格工具推荐这样做,我记得看到一些unix命令行工具警告丢失空行。

有一个额外的空行是什么原因?

80342 次浏览

如果文本文件中的最后一行数据没有以换行符或回车/换行符组合结束,许多旧工具就会出错。他们忽略了这一行,因为它以^Z (eof)结尾。

除了在文本编辑器中移动到文件末尾时,它是一个更好的光标位置之外。

在文件末尾使用换行符可以简单地检查文件是否被截断。

文件末尾的空行出现,以便从输入流的标准读取将知道何时终止读取,通常返回EOF表示已到达结束。大多数语言都可以处理EOF标记。因为这个原因,在过去,在DOS下,EOF标记是F6键或Ctrl-Z,对于*nix系统,它是Ctrl-D。

大多数(如果不是全部的话)实际上会一直读到EOF标记,以便运行时库从输入中读取的功能知道何时停止进一步读取。当您为追加模式打开流时,它将擦除EOF标记并写入过去,直到显式调用close,它将在该点插入EOF标记。

旧的工具期望一个空行,后面跟着EOF标记。现在,工具可以处理空行并忽略它。

有些语言根据输入行定义输入文件,其中每个输入行是由回车符结束的一系列字符。如果它们的语法是这样定义的,那么文件的最后有效行也必须以回车符结束。

此外,当您修改文件并在文件末尾追加一些代码时- diff(至少在标准配置中是git diff)将显示您更改了最后一行,而您实际上所做的唯一一件事-添加了一个换行符。因此,cvs报告变得不那么方便。

如果您试图将两个文本文件连接在一起,如果第一个文本文件以换行符结束,您会更高兴。

如果按照与为什么在列表中允许尾随逗号?相同的推理将参数附加到文件中,还可以为更清晰的差异做一个参数

从链接的资源中复制了以下内容(并进行了一些修改):

改变:

s = [
'manny',
'jack',
]

:

s = [
'manny',
'jack',
'roger',
]

只涉及diff中的一行更改:

  s = [
'manny',
'jack',
+   'roger',
]

这击败了后面省略逗号时更令人困惑的多行差异:

  s = [
'manny',
-   'jack'
+   'jack',
+   'roger'
]

这是因为文本文件的定义。当你在任何unix环境中创建一个新的文本文件时,该文件的内容是换行字符 '\n'

如果不这样做,文件就不能真正地将其标识为文本文件。现在,一旦我们将代码添加到这个文本文件中,它就不会删除定义文本文件本身的初始新行。

这个问题,以及现有的大多数答案,似乎都是基于一种误解。

ASCII控制字符,通常称为“换行符”。(U+000A换行,\n in C) 开始(unix风格)文本文件的新行。它结束文本文件的当前行。如果文本文件的最后一个字符是U+000A,则在中间有空行。U+000A和文件系统的EOF标记(无论它是如何实现的)。相反,如果一个(非空)文本文件的最后一个字符是 U+000A,则文件的最后一行__abc5被认为是“不完整的”。

用一些例子可能会更清楚:

该文件包含两行完整的文本。它不包含第三个空行。

$ printf 'first\nsecond\n' | xxd
00000000: 6669 7273 740a 7365 636f 6e64 0a         first.second.

文件包含第三个空行。

$ printf 'first\nsecond\n\n' | xxd
00000000: 6669 7273 740a 7365 636f 6e64 0a0a       first.second..

并且文件只包含一个完整的行,加上第二个不完整的行。

$ printf 'first\nsecond' | xxd
00000000: 6669 7273 740a 7365 636f 6e64            first.second

有时,你想要的是一个不完整的结束行——例如,在PHP脚本的最后?>和EOF之间有一个换行符,可能会导致在一个糟糕的位置向渲染的HTML中发出额外的空白(我想链接到具体的例子,但今天早上我没有运气找到一个)。因此,好的文本编辑器会在UI中清楚地区分上述三种情况。

但是,旧的文本处理工具经常会错误地处理不完整的结尾行。例如,wc的某些实现不会将不完整的结尾行计算为行,而vi的某些实现将无声地向不以换行符结束的文件添加换行符,不管你是否希望这样做。因此,只有当你有特定的理由需要使用不完整的结尾行时,你才应该使用它们。

(注:据我所知,我刚才所说的一切也适用于dos风格的文本文件,其中使用双字节控制序列U+000D U+000A来结束一行,而不仅仅是U+000A。)