我试图计算一个简单字符串的 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..cb
1 则适用于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>
时^D
,sha256sum
将读取后的"abc\x0a"
字符串(即以 结尾) ,以及 后的空字符串(即读取大小为 0 的内容),这将解释为文件结尾。LF
<newline>
""
^D
sha256sum
当你输入时abc
,然后^D
两次,sha256sum
将读取"abc"
第一个之后的字符串^D
,然后再次读取""
第二个之后的空字符串^D
。
因此,在前一种情况下,输出将有一个额外的换行符,并且校验和sha256sum
将会不同。
对于常规文件,sha256sum
将继续读取,直到到达文件结尾,其中,仅在上述两种情况下,读取将返回空字符串。情况类似,sha256
完全不知道它的输入是终端、管道或常规文件。