文件末尾没有换行符

Pac*_*ier 430 git git-svn

在做的git diff时候会说"文件末尾没有新行".

好的,文件末尾没有换行符.有什么大不了的?

这条消息有什么意义,它试图告诉我们什么?

Ale*_*ysh 427

它表示您'\n'在文件末尾没有换行符(通常称为CR或CRLF).

也就是说,简单来说,文件中的最后一个字节(或者如果你在Windows上的字节)不是换行符.

显示该消息是因为否则无法区分结尾处有换行符的文件与不换行换行符的文件之间的区别.Diff必须输出换行符,否则结果将更难以自动读取或处理.

请注意,如果文件格式允许,则始终将换行符作为最后一个字符是一种很好的样式.此外,例如,对于C和C++头文件,它是语言标准所要求的.

  • 出于好奇,你能解释为什么总是把换行作为最后一个角色被认为是好的风格吗?编辑:找到[此讨论](http://stackoverflow.com/questions/729692/why-should-files-end-with-a-newline). (129认同)
  • @PaulBellora从历史上看,它是由C语言标准做出的决定http://stackoverflow.com/a/729725/233098实际上,因为许多Unix工具需要或期望它能够正确显示http://stackoverflow.com/a/二十三万三千〇九十八分之七十二万九千七百九十五.从哲学上讲,因为文本文件中的每一行都以"行尾"字符结束 - 最后一行不应该是任何异常.以不同的方式思考它,让我们探讨逆向.如果有一个"行首"标记而不是"行尾",你会省略第一行的"行首"字符吗? (80认同)
  • @Joe这没有多大意义.换行符是*新行*,即行之间的分隔符,而不是行尾.我们没有行字符的开头,因为它们不是必需的.出于同样的原因,我们没有行尾字符. (27认同)
  • @Pacerier"停止培育新一代的黑猩猩程序员." 这对谈话没有任何影响.更糟糕的是,如果没有[给它5分钟](https://signalvnoise.com/posts/3124-give-it-five-minutes),你就会冒着误导程序员的风险.除非你孤立地工作,**自行车运动才是真正的问题**.它造成了不必要的延迟,基本上没有.偏离偏离是绝对有害的. (26认同)
  • @WORMSS"我的新手"与"新约会"不同.这就像发现任何其他类型的编程约定.你就去吧.你*可能*偏离,但你只是孤立自己.(或者在这种情况下,实际上是破坏了工具.)想想有多少其他人发现了一些Rails惯例,或PEP8,以及这些社区作为一个整体保持一致的原因,因为他们确实放弃了 - 尽管有相反的书面代码. (15认同)
  • @acjay我认为"行间分隔符号"与"行尾符号"之间存在固有的更好的结果.这两种观点本身都不是正确或错误,只是观察它的一种方式.我建议我们继续使用历史上实用的观点,因为我们已经这样做了,当你接受它时它*有意义.一致性很重要.没有必要以"行间分隔符"的名义打破它. (6认同)
  • @tobibeer使用一个更好的wiki解释器,你正在使用的(假设?)非常破碎. (6认同)
  • 只是为了记录:C++ **不** 要求文件以换行符结尾。*2.2.2 非空且不以换行符结尾的源文件,或在任何此类拼接发生之前以紧跟反斜杠字符开头的换行符结尾的源文件,应被视为文件中附加了一个额外的换行符。* (6认同)
  • 我真的看不出添加任何多余的东西是"好风格".如果diff无法处理没有的文件,则diff会出现问题.这些新行很容易造成真正的问题. (4认同)
  • @tobibeer你有一个可能导致问题的例子吗? (4认同)
  • @sricks ...一个wiki解释器,它将换行符解释为文字换行符并相应地呈现它们//想象一个构建在"wiki页面"上的模板系统,其中模板包含的每个模块在其末尾引入一个令人讨厌的换行符...每个按钮,每个工具栏,每个侧边栏,每个内容块//一个这样的维基是TiddlyWiki (4认同)
  • @Joe如果一切都是为了保持一致性,那么在文件末尾添加一个新行就是"新"的事情.我公司的任何人之前都没有听说过这种行为.我查阅它的唯一原因是因为Github对它做了如此重大的事情. (2认同)
  • 显然,如果我们只是在我们编写的每个文件中添加换行符,而不是改进 git diff 的 UI,会更容易。smh (2认同)

Dea*_*ean 90

这不仅仅是糟糕的风格,在文件上使用其他工具时可能会导致意外行为.

这是test.txt:

first line
second line
Run Code Online (Sandbox Code Playgroud)

最后一行没有换行符.让我们看看文件中有多少行:

$ wc -l test.txt
1 test.txt
Run Code Online (Sandbox Code Playgroud)

也许这就是你想要的,但在大多数情况下你可能希望文件中有2行.

此外,如果您想要合并文件,它可能不会按照您期望的方式运行:

$ cat test.txt test.txt
first line
second linefirst line
second line
Run Code Online (Sandbox Code Playgroud)

最后,如果要添加新行,它会使你的差异稍微嘈杂.如果您添加了第三行,它将显示第二行的编辑以及新添加.

  • cat的结果还可以,但是wc参数“ -l,--lines”是错误的。即使是手册,也说“打印换行计数”而不是“打印换行计数”。 (2认同)
  • 我什至无法用最近的 util linux (util-linux 2.34) 重现这个(wc 和 cat)。 (2认同)
  • @wget我使用的是util-linux 2.34,它可以确认这个答案描述的是当前的行为。我的猜测是您的编辑器添加了“\n”字符。 (2认同)

Nat*_*ike 24

唯一的原因是Unix历史上有一个以换行符结尾的所有人类可读文本文件的约定.当时,这在显示或加入文本文件时避免了额外的处理,并且避免了对包含其他类型数据的文件(例如,人类不可读的原始二进制数据)不同地处理文本文件.

由于这种惯例,那个时代的许多工具都期望结束换行符,包括文本编辑器,差异工具和其他文本处理工具.Mac OS X构建于BSD Unix之上,Linux开发为与Unix兼容,因此两种操作系统都继承了相同的约定,行为和工具.

Windows并不是与Unix兼容的,因此它没有相同的约定,大多数Windows软件都会处理得很好,没有尾随的换行符.

但是,由于Git是首先为Linux开发的,并且许多开源软件都是基于Unix兼容的系统构建的,如Linux,Mac OS X,FreeBSD等,大多数开源社区及其工具(包括编程语言)都在继续遵循这些惯例.

技术原因在1971年是有道理的,但在这个时代,它主要是惯例并保持与现有工具的兼容性.

  • 你的回答暗示这只是历史原因。这是错误的。1971 年适用的同样理由今天仍然适用。其他答案给出了更多细节 (9认同)
  • 个人不相信其他答案 (4认同)

Joh*_*hnD 18

它只是表明文件的末尾没有换行符.这不是一个灾难,它只是一个消息,更清楚的是,在命令行中查看差异时没有人.


Jas*_*eem 16

如果你在现有文件的末尾添加一个新行,该行在最后没有换行符,那么差异将显示旧的最后一行也是修改过的,当概念上它不是.

至少有一个很好的理由在最后添加换行符.

  • 我们可以在另一个方向上编写相同的东西:如果你在现有文件的末尾删除了一个新行,该行在最后已经有了换行符,那么差异也会显示旧的最后一行也是修改过的,当概念上它不是.至少有一个很好的理由在最后删除换行符. (2认同)
  • @gentiane你混淆了"新行"(新行)和"换行符"(1或2个字符分隔行的结尾) (2认同)
  • @TheincredibleJan在答案中使用它们的方式,两个术语具有不同的含义。我不知道您是想成为一个聪明人还是只是误解了正在发生的事情。 (2认同)

use*_*660 8

我在以前的回复中没有看到一件事。当文件的一部分被截断时,没有行尾的警告可能是警告。这可能是数据丢失的症状。


Les*_*use 6

此约定付诸实践的原因是因为在类UNIX操作系统上,换行符被视为行终止符和/或消息边界(这包括进程之间的管道,行缓冲等).

例如,考虑将仅具有换行符的文件视为单个空行.相反,长度为零字节的文件实际上是一个零行的空文件.这可以根据wc -l命令确认.

总而言之,这种行为是合理的,因为如果\n字符仅仅是行分隔符而不是行终止符,则没有其他方法可以区分空文本文件与具有单个空行的文本文件.因此,有效的文本文件应始终以换行符结尾.唯一的例外是文本文件是否为空(没有行).

  • 为什么我被否决了-2?我不仅指出了其他答案所陈述的内容(即标准的基于 UNIX 的工具期望换行符作为行的终止符),而且还指出没有办法区分空文件和单个空行,这绝对是正确的。我专门回答了最初的问题“这条消息的意义是什么?它想告诉我们什么?” (3认同)
  • 我没有对你投反对票,但这个响应似乎特定于 Unix 类型系统,因为它仅适用于换行符只是换行符时。目前尚不清楚这是否适用于此。此外,如果文件仅包含空行,则警告似乎毫无用处。不过,我避免使用 Stackoverflow,因为人们经常在没有解释的情况下投反对票。 (2认同)

小智 5

核心问题是如何定义行以及行尾字符序列是否为行的一部分。基于UNIX的编辑器(例如VIM)或工具(例如Git)使用EOL字符序列作为行终止符,因此它是行的一部分。这类似于在C和Pascal中使用分号(;)。在C中,分号终止语句,在Pascal中,将它们分开。


小智 5

这实际上确实会导致问题,因为行结尾会自动修改脏文件而不对其进行任何更改。请参阅此帖子以获取解决方案。

git 用 CRLF 替换 LF