为何在stdin中输入内容需要按两次CTRL+D

之前一直没注意到这样的问题(也许是碰到过又没有仔细思考,侧面印证了我理论与实践的双重匮乏):
在standard input中输入内容,按一下Ctrl+D并不能结束输入,需要再按一下才有用,这次在终端中使用shasum命令的时候终于碰上了,搜索一番弄了个明白,总结如下:

举个例子,计算字符串nihao的sha1值。

shasum命令可以从stdin中获得内容来计算hash:shasum --表示从stdin读取,
输入完毕后,按一下Enter回车键来换行,再按Ctrl+D(即EOF)来表示输入完毕。过程如下:

MacBookAir:~ Halley$ shasum -
nihao
8af88d48ec099be3a1329b936c88e6518f04c731  -
MacBookAir:~ Halley$ 

与之等价的写法是:

MacBookAir:~ Halley$ echo "nihao" | shasum
8af88d48ec099be3a1329b936c88e6518f04c731  -
MacBookAir:~ Halley$ 

但是需要注意的是,以上两种方式,计算的是”nihao
“(留意最后的换行符)的sha1,因为在第一种方式中你按了Enter键,而第二种方式echo命令默认会在最后输出

字符串带有换行符显然不是我们想要的,所以要对上述两种方式各自进行改进。
第一种:
Enter,Ctrl+D,换成Ctrl+D+D

MacBookAir:~ Halley$ shasum -
nihao23fcf96d70494b81c5084c0da6a6e8d84a9c5d20  -
MacBookAir:~ Halley$ 

上面的输出中nihao和hash结果连在了一起,该过程其实是输入完nihao后,连按了两次Ctrl+D。由于stdin输入的内容和stdout输出的hash中间没有
的介入,导致结果难以阅读,所以这种方式并不友好。

第二种:
给echo添加-n参数,表示echo最后不输出new line。

MacBookAir:~ Halley$ echo -n "nihao" | shasum
23fcf96d70494b81c5084c0da6a6e8d84a9c5d20  -
MacBookAir:~ Halley$ 

可以看到,改进过的版本得到的hash跟开始时是截然不同的。这才是我们需要的正确版本。

回到正题,来解释为何需要按两次Ctrl+D才能结束输入,原因是EOF只有在输入缓冲区为空的时候才起作用。输入内容后,按EnterCtrl+D,都会触发清空输入缓冲区的操作,此时再按Ctrl+D发送EOF才有效果,两者不同的是,Enter输入了
并附带刷新了输入缓冲区,而第一下Ctrl+D仅仅刷新了输入缓冲区。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据