为什么Vim会在文件末尾添加一个新行?

51

我经常使用WordPress,并且有时会暂时更改WordPress核心文件以了解其运行原理,特别是在调试时。今天给我带来了一个小惊喜。当我准备将更改提交到我的git存储库时,我注意到git status将其中一个WordPress文件标记为未暂存的更改。我记得在关闭文件之前撤消了对该文件所做的所有更改,因此我决定使用diff查看发生了什么变化。我将项目中的文件与我保存在下载目录中的WordPress副本上的文件进行了比较。结果发现两个文件在结尾处不同。 diff指出原始文件末尾缺少一个换行符:

1724c1724
< }
\ No newline at end of file
---
> }

我甚至没有碰那一行。我所做的更改位于一个大文件的中间某处。这导致我认为 vim 在文件末尾添加了一个新行字符。为什么会发生这种情况?


这不是VIM禁用文件末尾自动换行的重复。这个问题在询问原因:“为什么Vim会这样做?” - Peque
谢谢Peque。在构造句子的小细节上,有时候会让所有差异变得非常明显。 - Buzu
5个回答

60
我看到的所有答案都回答了问题“我如何防止Vim在文件结尾处添加一个换行符?”,而问题是“Vim为什么会在文件结尾添加一个换行符?”。我的浏览器搜索引擎把我带到了这里,但我没有找到那个问题的答案。
这与POSIX标准如何定义一行有关(请参见为什么文件应该以换行符结束?)。所以,基本上,一行是:
3.206 行(Line)
一个由零个或多个非 <newline> 字符组成并以一个终止的 <newline> 字符结束的序列。
因此,它们都需要以换行符结尾。这就是为什么Vim默认情况下总是添加一个换行符的原因(因为根据POSIX,它应该在那里)。
它不是唯一执行此操作的编辑器。GNOME中默认的文本编辑器Gedit也会这样做。

编辑

许多其他工具也期望那个换行符。例如,见: 你可能还想参考:Vim显示文件结尾处的换行符

1
有时候,人们希望编辑器完全按照用户输入的内容进行操作,即使在没有输入新行的情况下也是如此。但如果不期望出现新行,则这种标准可能会产生问题。虽然这种情况非常特殊,但我更喜欢只有在我自己输入时才出现新行。 - Sergio Abreu
1
我通过非常艰难的方式(2小时的调试)学到了一个教训,即如果tcsh脚本没有换行符,它将不会执行脚本的最后一行。我正在生成tcsh脚本,并忘记在文件末尾添加最后的\n。然后我注意到,如果我只是在vim中打开文件并除了保存之外什么都不做,它就突然开始工作了。 - Myles Prather

21

因为vim是一款文本编辑器,有时会自动“清理”你的文件。详情请参见http://vimhelp.appspot.com/vim_faq.txt.html#faq-5.4,其中介绍了如何在不添加结尾换行符的情况下编写文件:

如何在文件结尾处不添加换行符(EOL)来编写文件?

您可以关闭eol选项并打开binary选项以编写文件,文件结尾处没有EOL:
   :set binary
   :set noeol
   :w

另外,您也可以使用以下方法:
   :set noeol
   :w ++bin


谢谢您的回答和提供链接。看起来这是一个非常有用的常见问题集合。 - Buzu

6

在Vim中,添加新行是默认行为。如果您不需要它,请使用以下解决方案:VIM禁用文件末尾的自动换行符

要禁用,请将以下内容添加到您的.vimrc文件中

set fileformats+=dos

那个 Git 解决方案看起来也非常有趣。 - Max
谢谢,我不知道这是 Vim 的默认行为。 - Buzu
1
这对我不起作用。 我将 fileformats设置为unix,dos,mac(我在OS X上),但是vim仍然像OP描述的那样添加EOF行结尾。 - Andrew Ferrier
1
这里不起作用 - Linux Ubuntu。我必须像Max下面说的那样使用“set noeol binary”。 - Sergio Abreu

4
您可以将以下行放入您的.vimrc文件中。
autocmd FileType php setlocal noeol binary

这样做应该可以解决问题,但实际上你的方法有些错误。首先,php完全不会介意文件结尾,其次,如果你不想保存更改,请勿按下u,更糟糕的是手动尝试重新创建文件状态,而只需退出而不保存q!。如果你离开编辑器并因某种原因保存了文件,可以尝试使用git checkout <file>


使用 q! 是不起作用的,因为在某个时刻我已经保存了对该文件的更改。否则我无法看到我正在执行的测试结果。我已经知道如何恢复文件,但不知道为什么Vim会添加一个换行符。感谢您提供的要添加到vimrc文件中的行。 - Buzu

1
3.206 行 零个或多个非换行符字符序列加上一个终止符字符。
有趣的是,vim 允许您打开一个新文件,写入该文件,而该文件将为零字节。如果您打开一个新文件并使用 o 添加一行,然后写入该文件,它将有两个字符长。如果您重新打开该文件并删除第二行 dd 并写入该文件,则该文件将为一个字节长。重新打开该文件并删除唯一剩余的行并写入该文件,它将为零字节。因此,只要完全为空,vim 就允许您编写零字节文件。似乎违反了上面的 posix 定义。我猜...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接