一些编译器(尤其是C或C ++)会向您发出警告:

No new line at end of file


我认为这将是C程序员专用的问题,但是github在其中显示一条消息。提交视图:

\ No newline at end of file

用于PHP文件。

我了解此线程中解释的预处理器内容,但是该做什么呢?用PHP?是同一件事还是与include() vs \r\n主题有关?

在文件末尾换行有什么意义?

评论

与SO重复:stackoverflow.com/questions/729692/…

惹恼了人们。

如果对文件进行分类,则如果不以换行符结尾,则下一个提示将附加到最后的“行”。

#1 楼

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

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

本应在文本文件上运行的实用程序可能无法很好地应对以a结尾的文件新队;例如,历史上的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;这是在这些OS上读取以文本形式打开的文件时经常发生的情况)。有些操作系统没有换行符,而是有固定大小或可变大小的记录。在这些系统上,从文件到C源的映射在每个记录的末尾引入了\n。虽然这与unix并不直接相关,但这确实意味着,如果将缺少最终换行符的C源文件复制到具有基于记录的文本文件的系统中,然后再将其复制回,则结果要么不完整在初始转换中,最后一行被截断,或者在反向转换时,在其上加上了一个额外的换行符。

¹
示例:GNU sort的输出始终以换行符结尾。因此,如果文件foo缺少最后一个换行符,则您会发现sort foo | wc -c报告的字符比cat foo | wc -c多一个。


评论


关于“ ...一系列行,每个行都必须以换行符结尾(n1256§5.1.1.1)”->在重新查看更新的C11dr N1570时,除以下之外,没有找到对此的支持: “不为空的源文件应以换行符结尾,在进行任何此类拼接之前,不得紧接在反斜杠字符之后。” §5.1.1.22,但这似乎仅限于拼接规范。

–chux-恢复莫妮卡
16年8月4日在16:22



@chux这句话也出现在n1256中。最后一行必须以换行符结尾。不是最后一行的行显然还必须以换行符结尾,以指示该行结束并且下一行开始。因此,每行必须以换行符结尾。

–吉尔斯'所以-不再是邪恶的'
16年8月4日在16:40

嗯,对我来说,“发生源文件...发生拼接。”这一行可能仅限于拼接注意事项,而不是一般文件。但是我看到有人可能会以其他方式查看。也许我会找一篇帖子专注于此。

–chux-恢复莫妮卡
16年8月4日在17:01



>“因此diff使用此特殊文本\文件末尾没有换行符来区分未以换行符结尾的文件与已换行的文件。” Git不仅在比较文件时显示此文本。但是,即使将新文件添加到git中。我想这个论点是无效的。

–维克多·克鲁格利科夫(Viktor Kruglikov)
18年1月12日在15:54

为什么不只是更新旧工具,以免在缺少新行的情况下它们不会损坏...

–安德鲁(Andrew)
19年5月11日在14:27

#2 楼

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

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

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


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

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

评论


但是,关心文件串联是git的事吗?

–维克多·克鲁格利科夫(Viktor Kruglikov)
18年1月15日在9:33

难道不是您应该在cat操作中放入\ n吗?

–安德鲁(Andrew)
19年5月11日在14:28

就像是说:“有时我将字符串结尾附加\ n或空格,因此为了保持一致,我总是在字符串的两端加上\ n _____。”好吧,不,正确的做法是修剪字符串,然后正确地将它们连接起来。

–安德鲁(Andrew)
19年5月11日14:29



@ViktorKruglikov关心您的文件内容是git的事,是的。 Git可以帮助您保持数据一致性。如果要忽略换行符,将无法达到目的。按照同样的思路,准确复制您提供的数据是猫的事;不得在您未明确要求的中间添加随机字符。

– zaTricky
20/09/21在16:35



#3 楼

有两个方面:


有些C编译器如果不以换行符结尾则无法解析最后一行。 C标准指定C文件应以换行符结尾(C11、5.1.1.2、2),而没有换行符的最后一行将产生未定义的行为(C11,J.2,第二项)。也许出于历史原因,因为在编写第一个标准时,此类编译器的某些供应商才是委员会的一部分。因此,GCC发出的警告。
diff程序(如git diff,github等所使用的程序)显示文件之间的逐行差异。当只有一个文件以换行符结尾时,它们通常会打印一条消息,因为否则您将看不到这种差异。例如,如果两个文件之间的唯一区别是最后一个换行符的存在,而没有提示,则看起来两个文件都是相同的,当diffcmp返回退出代码不相等成功和文件的校验和时(例如通过md5sum)不匹配。


评论


与差异程序有意义

– Thamaraiselvam
19年5月7日在6:36

听起来差异应该更聪明。

–安德鲁(Andrew)
19年5月11日在14:32

@安德鲁,不,不是。如果有差异,则diff预期会打印差异。并且,如果一个文件的最后一个字符使用换行符,而另一个文件则没有,那么输出中的区别一定很明显。

–maxschlepzig
19年5月11日14:42

您的后一种说法是正确的。但是,差异查看器不必首先显示“换行符”(\ n),而可以仅显示“换行符”。

–安德鲁(Andrew)
19年5月11日14:45



#4 楼

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

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

注意:关于C编译器的警告,我想他们为最终向后兼容目的而坚持使用最后的换行符。如果不是以\n(或其他与系统相关的行末字符序列)结尾,很老的编译器可能不接受最后一行。

评论


“我猜他们为实现向后兼容性而坚持使用最后的换行符”-否,他们坚持这样做是因为C标准要求这样做。

–MestreLion
13年8月28日在9:25

@MestreLion C需要最后一个换行符以获取C源代码(C11§5.1.1.22)。请注意,对于文本文件I / O,C具有“是否在实现的最后一行定义了换行符”。 §7.21.22

–chux-恢复莫妮卡
18/09/4在13:39



谁在使用非常老的编译器?停止使用它们。

–安德鲁(Andrew)
19年5月11日在14:31

@MestreLion:为什么您认为C标准要求它…

–StéphaneGimenez
19年8月1日在10:11

@StéphaneGimenez:不同操作系统之间的一致性,更好的兼容性和互操作性(POSIX还定义了以'\ n'结尾的行)

–MestreLion
19年8月3日,下午3:37

#5 楼

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

这可能会导致使用诸如git blamehg annotate之类的命令会产生不需要的结果。

评论


听起来差异仅需更智能。

–安德鲁(Andrew)
19年5月11日在14:32

差异化工具很聪明。他们注意到文件的细微变化(这很重要,因为它不可避免地会改变文件的哈希值)。而且,当为人类输出数据时,GNU diff和git diff都接受-w选项以忽略空格更改。

– joeytwiddle
19-10-16在3:22

#6 楼

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

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

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

,如果您依赖于OS,则这一点很重要表示行数或拆分/帮助解析文件的工具。鉴于PHP是一种脚本语言,尤其是在早期甚至现在(我不知道/假定),它完全有可能像OS这样依赖于操作系统。

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