it-swarm.cn

在文件末尾添加新行有什么意义?

一些编译器(尤其是C或C++编译器)会向您发出有关以下内容的警告:

_No new line at end of file
_

我以为这只是C程序员的问题,但是github在commit视图中显示了一条消息:

_\ No newline at end of file
_

对于PHP文件。

我了解 此线程 中解释的预处理程序,但是与PHP有什么关系?是相同的include()还是与_\r\n_ vs _\n_主题相关?

在文件末尾添加新行有什么意义?

197
Philipp Stephan

这不是在文件末尾添加额外的换行符,而是关于不删除应该存在的换行符。

Unix下的 文本文件 由一系列 组成,每行以 换行符\n)结尾。因此,不为空且不以换行符结尾的文件不是文本文件。

本应在文本文件上运行的实用程序可能无法很好地应对不以换行符结尾的文件。例如,历史上的Unix实用程序可能会忽略最后一个换行符之后的文本。 [〜#〜] gnu [〜#〜] 实用程序具有对非文本文件表现得很好的策略,大多数其他现代实用程序也是如此,但是对于带有以下内容的文件,您仍然可能会遇到奇怪的行为缺少最后一个换行符¹。

对于GNU diff,如果要比较的文件之一以换行符结尾而不是另一个换行符,则要注意这一事实。由于diff是面向行的,因此无法表明这一点。通过为其中一个文件存储换行符,而不为其他文件存储换行符–换行符是必要的,以指示每行在diff文件中的开始和结束位置,因此diff使用此特殊文本\ No newline at end of file区分没有以换行结尾的文件和以换行结尾的文件。

顺便说一下,在C上下文中,源文件类似地由一系列行组成。更精确地说,翻译单元在实现中被视为一系列行,每行必须以换行符结尾( n1256 §5.1.1.1)。在UNIX系统上,映射很简单。在DOS和Windows上,每个CR LF序列(\r\n)]都映射到换行符(\n;这是在读取以文本形式打开的文件时总是发生的情况这些操作系统)。有些操作系统没有换行符,而是具有固定大小或可变大小的记录;在这些系统上,从文件到C源的映射在_处引入\n每条记录的末尾。虽然这与Unix没有直接关系,但这确实意味着,如果您将缺少最后换行符的C源文件复制到具有基于记录的文本文件的系统中,然后将其复制回去,要么以不完整的最后一行在初始转换中被截断为结尾,要么以反向转换时附加在其上的额外的换行符结束。

¹ 示例:GNU sort的输出始终以换行符结尾。因此,如果文件foo缺少其最后的换行符,则您会发现sort foo | wc -c再次报告字符不能超过cat foo | wc -c

223

不一定是原因,而是文件未以换行结尾的实际后果:

考虑如果要使用cat处理多个文件,将会发生什么情况。例如,如果您想在3个文件的行首找到单词foo

cat file1 file2 file3 | grep -e '^foo'

如果file3的第一行以foo开头,但file2没有最后的\n在其最后一行之后,grep不会发现这种情况,因为grep会将file2中的最后一行和file3中的第一行视为一行。

因此,为了保持一致性并避免出现意外,我尝试使文件始终以新行结尾。

48
Sergio Acosta

有两个方面:

  1. 有些/有些C编译器如果不以换行符结尾则无法解析最后一行。 C标准指定C文件应以换行符结尾(C11、5.1.1.2、2),而没有换行符的最后一行将产生未定义的行为(C11,J.2,第二项)。也许出于历史原因,因为在编写第一个标准时,此类编译器的某些供应商才是委员会的一部分。因此由海湾合作委员会发出警告。

  2. diff个程序(如git diff,github等。)显示文件之间的逐行差异。当只有一个文件以换行符结尾时,它们通常会打印一条消息,因为否则您将看不到这种区别。例如,如果两个文件之间的唯一区别是最后一个换行符的存在,而没有提示,则当diffcmp返回一个exit-代码不相等的成功和文件的校验和(例如,通过md5sum)不匹配。

17
maxschlepzig

您从github获得的\ No newline at end of file出现在补丁的末尾(以 diff格式 ,请参见“统一格式”部分的末尾)。

编译器不在乎文件末尾是否有换行符,但是git(和diff/patch实用程序)必须考虑这些内容。这有很多原因。例如,忘记在文件末尾添加或删除换行符会更改其哈希值(md5sum/_sha1sum)。同样,文件也不总是程序,最后的\n可能会有所不同。

:关于C编译器的警告,我猜他们为实现向后兼容性而坚持使用最后的换行符。如果不以\n(或其他与系统相关的行末字符序列)结尾,则非常老的编译器可能不接受最后一行。

12
Stéphane Gimenez

保留差异历史记录也很重要。如果文件结尾没有换行符,则diff实用程序会在将文件末尾添加任何内容时更改最后一行(因为\n被添加到其中。

诸如git blamehg annotate

6
Hosam Aly

POSIX,这是IEEE指定的一组标准,用于维护操作系统之间的兼容性。

其中之一是“行”的定义,该行是零个或多个非字符加上终止换行符的序列。

因此,要使最后一行被识别为实际的“行”,它应该具有终止的新行字符。

如果您依靠OS工具来说行数或分割/帮助解析文件,那么这很重要。给定PHP是一种脚本语言,它完全有可能,尤其是在早期甚至现在(我不知道/假定)),它具有类似OS的依赖关系。

实际上,大多数操作系统都不完全符合POSIX,人类也不是那种喜欢甚至不愿终止新产品线的机器。因此,对于大多数事情而言,它只是关心,警告或仅留下最后一段文字的杂物,实际上是一行,因此只需将其包括在内。

4
user3379747