为什么 sha256sum 对文件结束和输入信号结束的处理方式不同?

为什么 sha256sum 对文件结束和输入信号结束的处理方式不同?

我试图计算一个简单字符串的 sha256,即“abc”。我发现使用sha256sum像这样的实用程序:

sha256sum file_with_string

给出的结果与以下内容相同:

sha256sum # enter, to read input from stdin
abc
^D

即:

edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb

请注意,在输入结束信号之前,另一个换行符被馈送到标准输入。


起初让我烦恼的是,当我决定使用在线校验和计算器验证它时,结果不同:

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

我认为这可能与我输入到标准输入的第二个换行符有关,所以我这次尝试插入 ^D 两次(而不是使用换行符)结果如下:

abcba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

现在,这当然格式很差(由于缺少换行符),但除此之外,它与上面的匹配。

之后,我意识到我显然无法理解 shell 中输入解析的一些内容。我仔细检查了一下,没有多余的新队在我最初指定的文件中,那么为什么我会遇到这种行为呢?

答案1

区别在于换行符。首先,我们收集abc和的 sha256sums abc\n

$ printf 'abc\n' | sha256sum 
edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb  -
$ printf 'abc' | sha256sum 
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad  -

因此,ba...ad总和适用于字符串abc,而ed..cb1 则适用于abc\n。现在,如果您的文件为您提供输出ed..cb,则意味着您的文件有换行符。并且,考虑到“文本文件”要求尾随换行符,如果您创建新文件,大多数编辑器都会为您添加一个换行符。

要获取没有换行符的文件,请使用printf上面的方法。请注意file,如果您的文件没有换行符,将如何警告您:

$ printf 'abc' > file
$ file file
file: ASCII text, with no line terminators

$ printf 'abc\n' > file2
$ file file2
file2: ASCII text

现在:

$ sha256sum file file2
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad  file
edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb  file2

答案2

sha256sum # enter, to read input from stdin
abc
^D

所以我^D这次尝试插入两次(而不是使用换行符)

当您在 tty 上按^D( )VEOF规范模式(任何命令行窗口、xterm 等中的默认设置),终端驱动程序(“行规则”)立即使已缓冲的数据可供从 tty 读取的进程使用,而无需等待换行符。

当您输入abc,<newline>^Dsha256sum将读取后的"abc\x0a"字符串(即以 结尾) ,以及 后的空字符串(即读取大小为 0 的内容),这将解释为文件结尾。LF<newline>""^Dsha256sum

当你输入时abc,然后^D 两次sha256sum将读取"abc"第一个之后的字符串^D,然后再次读取""第二个之后的空字符串^D

因此,在前一种情况下,输出将有一个额外的换行符,并且校验和sha256sum将会不同。

对于常规文件,sha256sum将继续读取,直到到达文件结尾,其中,仅在上述两种情况下,读取将返回空字符串。情况类似,sha256完全不知道它的输入是终端、管道或常规文件。

相关内容