使用 cat 创建文件时,我必须输入 ctrl+d 两次才能完成输入,这是预期的吗?

Faj*_*iya 31 cat newlines

我刚刚学会了使用命令创建新文件的技巧cat。根据我的测试,如果最后一行后面没有换行符,我必须输入ctrl+d两次才能完成输入,如下所示。

[root@192 ~]# cat > 测试
A
乙
ctrl+d[root@192 ~]# cat > 测试
A
b ctrl+dctrl+d[root@192 ~]#

这是预期的吗?为什么会有这种行为?

ilk*_*chu 47

是的,这是预期的。

我们说 Ctrl-D 可以cat在输入中看到“文件结尾”,然后停止读取并退出,但事实并非如此。由于这是在终端上,所以没有实际的“结束”,事实上它并不是检测到的真正的“文件结束” 而是任何read()零字节。

通常,read()系统调用不会返回零字节,除非知道没有更多可用字节,例如在文件末尾。当从没有可用数据的网络套接字读取时,预计新数据将在某个时刻到达,因此系统调用将阻塞并等待某些数据到达,而不是零字节读取,或者返回错误说它会阻止。如果连接被关闭,那么它将返回零字节。话又说回来,即使在文件上,在末尾(或过去)读取也不是无休止的最终结束,因为另一个进程可以向文件写入一些内容以使其更长,之后新的读取尝试将返回更多数据。(这就是 的简单实现所tail -f要做的。)

对于许多用例来说,将“零字节读取”视为“检测到文件末尾”恰好工作得足够好,以至于在实践中它们被认为实际上是同一件事。


Ctrl-D 在这里的作用是告诉终端驱动程序传递到目前为止所给出的所有内容,即使它还不是完整的行。在一行的开头,全部是零字节,被检测为 EOF。但在字母 后b,第一个 Ctrl-D 发送b,然后下一个发送在 后输入的零字节b,现在被检测为 EOF。

cat您还可以看到如果您在没有重定向的情况下运行会发生什么。它看起来像这样,斜体部分是我输入的内容:

$
fooCtrl-D foo

当按下 Ctrl-D 时,cat获取输入foo,将其打印回来并继续等待输入。该行看起来像foofoo,之后没有换行符,因此光标停留在末尾。

  • 另一个有助于理解的有用工具是另一个终端中的“strace -p $(pidof cat)”(或非 Linux 上的等效工具)。然后,您可以看到它执行的实际“read(0, ...)”和“write(1, ...)”系统调用,每当您按下 EOF 或 EOL 键提交该行时,都会返回 read 系统调用- 编辑缓冲区。(`stty -a`) (4认同)