“文件末尾无换行符”的意义是什么?日志?

发布于 2024-11-04 05:56:34 字数 81 浏览 1 评论 0原文

当执行 git diff 时,它显示“No newline at end of file”。

这则消息的意义是什么?它想告诉我们什么?

When doing a git diff it says "No newline at end of file".

What's the significance of the message and what's it trying to tell us?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

南薇 2024-11-11 05:56:34

它表明文件末尾没有换行符(通常是 \n,又名 LF 或 CRLF)。

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

显示该消息是因为否则无法区分末尾有换行符的文件和没有换行符的文件。无论如何,Diff 都必须输出换行符,否则结果将难以自动读取或处理。

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

It indicates that you do not have a newline (usually \n, aka LF or CRLF) at the end of file.

That is, simply speaking, the last byte (or bytes if you're on Windows) in the file is not a newline.

The message is displayed because otherwise there is no way to tell the difference between a file where there is a newline at the end and one where is not. Diff has to output a newline anyway, or the result would be harder to read or process automatically.

Note that it is a good style to always put the newline as a last character, in text files, if it is allowed by the file format. Furthermore, for example, for C and C++ header files it is required by the language standard.

清欢 2024-11-11 05:56:34

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

这是test.txt

first line
second line

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

$ wc -l test.txt
1 test.txt

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

另外,如果您想合并文件,它的行为可能不会像您期望的那样:

$ cat test.txt test.txt
first line
second linefirst line
second line

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

It's not just bad style, it can lead to unexpected behavior when using other tools on the file.

Here is test.txt:

first line
second line

There is no newline character on the last line. Let's see how many lines are in the file:

$ wc -l test.txt
1 test.txt

Maybe that's what you want, but in most cases you'd probably expect there to be 2 lines in the file.

Also, if you wanted to combine files it may not behave the way you'd expect:

$ cat test.txt test.txt
first line
second linefirst line
second line

Finally, it would make your diffs slightly more noisy if you were to add a new line. If you added a third line, it would show an edit to the second line as well as the new addition.

画尸师 2024-11-11 05:56:34

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

由于这一约定,那个时代的许多工具都期望以换行符结尾,包括文本编辑器、比较工具和其他文本处理工具。 Mac OS X 是在 BSD Unix 基础上构建的,而 Linux 是为了与 Unix 兼容而开发的,因此这两个操作系统都继承了相同的约定、行为和工具。

Windows 并不是为了与 Unix 兼容而开发的,因此它没有相同的约定,并且大多数 Windows 软件都可以很好地处理没有尾随换行符的情况。

但是,由于 Git 首先是为 Linux 开发的,并且许多开源软件是在 Linux、Mac OS X、FreeBSD 等 Unix 兼容系统上构建的,因此大多数开源社区及其工具(包括编程语言)仍在继续遵守这些约定。

技术原因在 1971 年是有意义的,但在这个时代,主要是惯例以及保持与现有工具的兼容性。

The only reason is that Unix historically had a convention of all human-readable text files ending in a newline. At the time, this avoided extra processing when displaying or joining text files, and avoided treating text files differently to files containing other kinds of data (eg raw binary data which isn't human-readable).

Because of this convention, many tools from that era expect the ending newline, including text editors, diffing tools, and other text processing tools. Mac OS X was built on BSD Unix, and Linux was developed to be Unix-compatible, so both operating systems have inherited the same convention, behaviour and tools.

Windows wasn't developed to be Unix-compatible, so it doesn't have the same convention, and most Windows software will deal just fine with no trailing newline.

But, since Git was developed for Linux first, and a lot of open-source software is built on Unix-compatible systems like Linux, Mac OS X, FreeBSD, etc, most open-source communities and their tools (including programming languages) continue to follow these conventions.

There are technical reasons which made sense in 1971, but in this era it's mostly convention and maintaining compatibility with existing tools.

孤者何惧 2024-11-11 05:56:34

如果您在现有文件末尾添加新行文本,而该文件末尾还没有换行符,则差异将显示旧的最后一行:已被修改,尽管从概念上来说并没有。

这至少是在末尾添加换行符的一个充分理由。

示例

一个文件包含:

A() {
    // do something
}

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d              something.}

您现在将其编辑为

A() {
    // do something
}
// Useful comment

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055  something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a    seful comment..

git diff 将显示:

-}
\ No newline at end of file
+}
+// Useful comment.

换句话说,它显示了比概念上更大的差异。它表明您删除了行 } 并添加了行 }\n。事实上,这就是发生的事情,但它不是概念上发生的事情,所以它可能会令人困惑。

If you add a new line of text at the end of the existing file which does not already have a newline character at the end, the diff will show the old last line as having been modified, even though conceptually it wasn’t.

This is at least one good reason to add a newline character at the end.

Example

A file contains:

A() {
    // do something
}

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d              something.}

You now edit it to

A() {
    // do something
}
// Useful comment

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055  something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a    seful comment..

The git diff will show:

-}
\ No newline at end of file
+}
+// Useful comment.

In other words, it shows a larger diff than conceptually occurred. It shows that you deleted the line } and added the line }\n. This is, in fact, what happened, but it’s not what conceptually happened, so it can be confusing.

简美 2024-11-11 05:56:34

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

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

总而言之,这种行为是合理的,因为如果 \n 字符仅仅是行分隔符而不是行终止符。因此,有效的文本文件应始终以换行符结尾。唯一的例外是文本文件是否为空(无行)。

The reason this convention came into practice is because on UNIX-like operating systems a newline character is treated as a line terminator and/or message boundary (this includes piping between processes, line buffering, etc.).

Consider, for example, that a file with just a newline character is treated as a single, empty line. Conversely, a file with a length of zero bytes is actually an empty file with zero lines. This can be confirmed according to the wc -l command.

Altogether, this behavior is reasonable because there would be no other way to distinguish between an empty text file versus a text file with a single empty line if the \n character was merely a line-separator rather than a line-terminator. Thus, valid text files should always end with a newline character. The only exception is if the text file is intended to be empty (no lines).

记忆里有你的影子 2024-11-11 05:56:34

它只是表明文件末尾没有换行符。这不是一场灾难,它只是一条消息,让您更清楚地知道在命令行中查看差异时不存在灾难。

It just indicates that the end of the file doesn't have a newline. It's not a catastrophe it's just a message to make it clearer that there isn't one when looking at a diff in the command line.

凉城凉梦凉人心 2024-11-11 05:56:34

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

There is one thing that I don't see in previous responses. Warning about no end-of-line could be a warning when a portion of a file has been truncated. It could be a symptom of missing data.

韬韬不绝 2024-11-11 05:56:34

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

The core problem is what you define line and whether end-on-line
character sequence is part of the line or not. UNIX-based editors
(such as VIM) or tools (such as Git) use EOL character sequence as
line terminator, therefore it's a part of the line. It's similar to
use of semicolon (;) in C and Pascal. In C semicolon terminates
statements, in Pascal it separates them.

故人爱我别走 2024-11-11 05:56:34

什么

在进行 git diff 时,它显示“文件末尾没有换行符”。

在某些方面,是的,但它更加微妙和微妙。

在执行 git diff 时,git 显示文件版本之间的差异,在这些文件不同的地方显示为块。这可能包括文件末尾的块。

如果文件的两个版本都不以换行符结尾,则将读取块的末尾,

\ No newline at the end of file

而如果只有一个版本不以换行符结尾,则块将以

-last line
\ No newline at the end of file
+new last line

-last line
+new last line
\ No newline at the end of file

为什么?

这条消息的意义是什么

原因很简单。 git diff 的主要目的之一是明确地显示更改,以便它可以用作 git apply输入。为此,Git 需要知道在应用 diff 时应该如何处理换行符。应该删除、保留还是更改它们?

\ No newline at the end of file 是一种实现此目的的方法。它对于想要了解此类更改的人们也很有帮助,因为在某些情况下,有或没有换行符对文件来说很重要。

它想告诉我们什么?

好吧,只是这个文件末尾没有换行符。或者说以前没有,但现在有了。或者说曾经有但现在没有了。

What

When doing a git diff it says "No newline at end of file".

In some ways, yes, but it's more nuanced and subtle.

When doing a git diff, git shows the difference between versions of files, displayed as chunks where those files differ. This may include a chunk at the end of the file.

If both versions of the file do not end in a newline, the end of the chunk will read

\ No newline at the end of file

whereas if only one version don't end in a newline, the chunk will end in either

-last line
\ No newline at the end of file
+new last line

or

-last line
+new last line
\ No newline at the end of file

Why?

What's the significance of the message

The reason is simple. One of the main purpose of git diff is display changes, unambiguously so that it can be used as a input to git apply. To do this, Git needs to know what it is supposed to do with newlines when applying a diff. Should it remove, keep or change them?

The \ No newline at the end of file is a way of doing that. It's also helpful to humans that want to be aware of such changes, because in some instances having or not having newlines is important to the file.

and what's it trying to tell us?

Well, just that there is no newline at the end of this file. Or that there wasn't but now there is. Or that there was but now isn't.

浅忆 2024-11-11 05:56:34

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

git 用 CRLF 替换 LF

This actually does cause a problem because line endings are automatically modified dirtying files without making any changes to them. See this post for resolution.

git replacing LF with CRLF

乖乖公主 2024-11-11 05:56:34

源文件通常由工具连接(C、C++:头文件,Javascript:捆绑程序)。如果省略换行符,可能会引入严重的错误(其中一个源文件的最后一行与下一个源文件的第一行连接)。希望所有源代码连接工具都能在连接的文件之间插入换行符,但情况似乎并非总是如此。

问题的关键是 - 在大多数语言中,换行符具有语义含义,并且文件结尾不是换行符的语言定义替代品。因此,您应该使用换行符来终止每个语句/表达式 - 包括最后一个。

Source files are often concatenated by tools (C, C++: header files, Javascript: bundlers). If you omit the newline character, you could introduce nasty bugs (where the last line of one source is concatenated with the first line of the next source file). Hopefully all the source code concat tools out there insert a newline between concatenated files anyway but that doesn't always seem to be the case.

The crux of the issue is - in most languages, newlines have semantic meaning and end-of-file is not a language defined alternative for the newline character. So you ought to terminate every statement/expression with a newline character -- including the last one.

血之狂魔 2024-11-11 05:56:34

您的原始文件可能没有换行符。

但是,某些编辑器(例如 Linux 中的 gedit)会在文件末尾默默地添加换行符。使用此类编辑器时您无法摆脱此消息。

我试图解决这个问题是使用 Visual Studio 代码编辑器 打开文件

该编辑器清楚地显示了最后一行您可以根据需要删除该行。

Your original file probably had no newline character.

However, some editors like gedit in linux silently adds newline at end of file. You cannot get rid of this message while using this kind of editors.

What I tried to overcome this issue is to open file with visual studio code editor

This editor clearly shows the last line and you can delete the line as you wish.

锦爱 2024-11-11 05:56:34
ubuntu
gt; vi source.cpp

:set binary noeol
ubuntu
gt; vi source.cpp

:set binary noeol
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文