Fajela Tajkiya Asked: 2022-05-04 13:57:12 +0800 CST2022-05-04 13:57:12 +0800 CST 2022-05-04 13:57:12 +0800 CST 使用 cat 创建文件时,我必须输入两次 ctrl+d 才能完成输入,这是预期的吗?[复制] 772 我刚刚学会了一个使用命令创建新文件的技巧cat。通过我的测试,如果最后一行没有换行,我必须键入ctrl+d两次才能完成输入,如下所示。 [root@192 ~]# cat > test 一个 b ctrl+d[root@192 ~]# cat > test 一个 b ctrl+dctrl+d[root@192 ~]# 这是预期的吗?为什么会有这种行为? cat newlines 2 个回答 Voted Best Answer ilkkachu 2022-05-04T14:10:02+08:002022-05-04T14:10:02+08:00 是的,这是预期的。 我们说 Ctrl-Dcat在输入中看到“文件结尾”,然后它停止读取并退出,但事实并非如此。由于那是在终端上,因此没有实际的“结束”,实际上它不是真正检测到的“文件结束” ,而是任何read()零字节。 通常,read()系统调用不会返回零字节,除非已知没有更多可用字节,例如在文件末尾。当从没有可用数据的网络套接字读取时,预计新数据将在某个时间到达,因此系统调用将阻塞并等待某些数据到达,而不是零字节读取,或者返回错误说它会阻塞。但是,如果连接被关闭,那么它将返回零字节。再说一次,即使在文件上,在(或过去)结束时读取也不是无休止的最终结束,因为另一个进程可以将某些内容写入文件以使其更长,之后新的读取尝试将返回更多数据。(这就是一个简单的实现tail -f会做的事情。) 对于许多将“读取零字节”视为“检测到文件结尾”的用例来说,它们恰好工作得很好,以至于在实践中它们实际上被认为是同一件事。 Ctrl-D 在这里所做的是告诉终端驱动程序传递到目前为止给出的所有内容,即使它还不是完整的行。在一行的开头,这都是零字节,被检测为 EOF。但是在字母之后b,第一个 Ctrl-D 发送b,然后下一个发送在 之后输入的零字节b,现在被检测为 EOF。 如果您只是在cat没有重定向的情况下运行,您还可以看到会发生什么。它看起来像这样,斜体部分是我输入的: $猫 fooCtrl-D foo 当按下 Ctrl-D 时,cat获取输入foo,将其打印回来并继续等待输入。该行看起来像foofoo,之后没有换行符,所以光标停留在最后。 Hastur 2022-05-05T04:40:07+08:002022-05-05T04:40:07+08:00 关于几句话。 据我快速浏览源代码可以看出,cat使用缓冲区来优化其工作流程。参考简单cat调用的行为,来自标准输入并且没有特殊的命令行选项: 当缓冲区为空时,单个Ctrl+D就足以退出; 如果不是,第一个 Ctrl-D 强制缓冲区转储(变为空),第二个被解释为退出命令。 这意味着,如果您运行 yourcat> test并简单地输入 Ctrl-D ,您将在当前目录中创建一个空文件(名为test),或者如果该文件已经存在,您将清空该文件,而无需第二个 Ctrl-D . 超出了这个问题的范围,但不是那么遥远:应该注意的是,如果您将字符发送到终端/shell 实例,那么不必要的第二个Ctrl-D可能会导致不必要的退出(主要连接到上面的示例)。
是的,这是预期的。
我们说 Ctrl-D
cat
在输入中看到“文件结尾”,然后它停止读取并退出,但事实并非如此。由于那是在终端上,因此没有实际的“结束”,实际上它不是真正检测到的“文件结束” ,而是任何read()
零字节。通常,
read()
系统调用不会返回零字节,除非已知没有更多可用字节,例如在文件末尾。当从没有可用数据的网络套接字读取时,预计新数据将在某个时间到达,因此系统调用将阻塞并等待某些数据到达,而不是零字节读取,或者返回错误说它会阻塞。但是,如果连接被关闭,那么它将返回零字节。再说一次,即使在文件上,在(或过去)结束时读取也不是无休止的最终结束,因为另一个进程可以将某些内容写入文件以使其更长,之后新的读取尝试将返回更多数据。(这就是一个简单的实现tail -f
会做的事情。)对于许多将“读取零字节”视为“检测到文件结尾”的用例来说,它们恰好工作得很好,以至于在实践中它们实际上被认为是同一件事。
Ctrl-D 在这里所做的是告诉终端驱动程序传递到目前为止给出的所有内容,即使它还不是完整的行。在一行的开头,这都是零字节,被检测为 EOF。但是在字母之后
b
,第一个 Ctrl-D 发送b
,然后下一个发送在 之后输入的零字节b
,现在被检测为 EOF。如果您只是在
cat
没有重定向的情况下运行,您还可以看到会发生什么。它看起来像这样,斜体部分是我输入的:当按下 Ctrl-D 时,
cat
获取输入foo
,将其打印回来并继续等待输入。该行看起来像foofoo
,之后没有换行符,所以光标停留在最后。关于几句话。
据我快速浏览源代码可以看出,
cat
使用缓冲区来优化其工作流程。参考简单cat
调用的行为,来自标准输入并且没有特殊的命令行选项:这意味着,如果您运行 your
cat> test
并简单地输入 Ctrl-D ,您将在当前目录中创建一个空文件(名为test
),或者如果该文件已经存在,您将清空该文件,而无需第二个 Ctrl-D .超出了这个问题的范围,但不是那么遥远:应该注意的是,如果您将字符发送到终端/shell 实例,那么不必要的第二个Ctrl-D可能会导致不必要的退出(主要连接到上面的示例)。