我使用CRC32很久以前从字符串中计算出校验和
echo -n "LongString" | crc32 # no output
我找到了用python计算它们的解决方案[1],但是没有直接的方法可以从字符串中计算出来?
# signed
python -c 'import binascii; print binascii.crc32("LongString")'
python -c 'import zlib; print zlib.crc32("LongString")'
# unsigned
python -c 'import binascii; print binascii.crc32("LongString") % (1<<32)'
python -c 'import zlib; print zlib.crc32("LongString") % (1<<32)'
[1]如何用Python计算CRC32以匹配在线结果?
我本人遇到了这个问题,我不想去"麻烦"安装crc32
。我想到了这个,尽管有点讨厌,它应该在大多数平台上工作,或者大多数现代的Linux ...
echo -n "LongString" | gzip -1 -c | tail -c8 | hexdump -n4 -e '"%u"'
只是为了提供一些技术细节,GZIP在最近的8个字节中使用CRC32,而-c
选项使其输出输出到标准输出,并且tail
剥离了最后8个字节。(如@markadler所建议的-1
,所以我们不会浪费时间实际进行压缩(。
hexdump
有点棘手,我不得不在我提出令人满意的东西之前对它进行了一段时间,但是这里的格式似乎正确地解析了GZIP CRC32作为一个32位编号:
-
-n4
仅采用GZIP页脚的相关前4个字节。 -
'"%u"'
是您的标准fprintf格式字符串,将字节格式为单个未签名的32位整数。请注意,这里有双引号嵌套在此处的单语。
如果您想要十六进制校验和,则可以将格式字符串更改为 '"%08x"'
(或大写六角形的 '"%08X"'
(,该字符串将格式化为8个字符(0填充(十六进制。
就像我说的那样,不是最优雅的解决方案,也许不是您想在性能敏感的情况下使用的方法,而是在使用命令的几乎普遍性的情况下可能会吸引的一种方法。
跨平台可用性的弱点可能是hexdump
配置,因为我已经看到了从平台到平台上的变化,而且有点麻烦。我建议如果您正在使用此功能,则应尝试一些测试值并与在线工具的结果进行比较。
编辑 @pedrogimeno在注释中建议,您可以将输出输送到od
而不是hexdump
中,而不是相同的结果,而无需贴心的选项。... | od -t x4 -N 4 -A n
用于十进制的HEX ... | od -t d4 -N 4 -A n
。
或仅使用过程替代:
crc32 <(echo -n "LongString")
(编辑:thx @tor-klingberg(
您的问题已经具有大多数答案。
echo -n 123456789 | python -c 'import sys;import zlib;print(zlib.crc32(sys.stdin.read())%(1<<32))'
正确提供3421780262
我更喜欢十六进制:
echo -n 123456789 | python -c 'import sys;import zlib;print("%08x"%(zlib.crc32(sys.stdin.read())%(1<<32)))'
cbf43926
请注意,有几种CRC-32算法:http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.32
我使用 cksum
并使用shell内置printf
转换为十六进制:
$ echo -n "LongString" | cksum | cut -d -f1 | xargs echo printf '%0X\n' | sh
5751BDB2
cksum
命令首先出现在4.4BSD Unix上,应在所有现代系统中都存在。
在ubuntu上,至少/usr/bin/crc32
是一个简短的perl脚本,您可以清楚地从其源头看到它所能做的就是打开文件。它没有从Stdin阅读的设施 - 它没有针对-
作为文件名的特殊处理,或-c
参数或类似的内容。
因此,您最简单的方法是使用它并制作临时文件。
tmpfile=$(mktemp)
echo -n "LongString" > "$tmpfile"
crc32 "$tmpfile"
rm -f "$tmpfile"
如果您真的不想编写文件(例如,数据比您的文件系统所能使用的更多 - 如果确实是一个"长字符串",那么不太可能是为了参数...(命名为管道。对于简单的非随机读者,这与文件是无法区分的:
fifo=$(mktemp -u)
mkfifo "$fifo"
echo -n "LongString" > "$fifo" &
crc32 "$fifo"
rm -f "$fifo"
请注意&
到背景的fifo
的过程,因为它将阻止直到下一个命令读取它。
要对临时文件的创建更加挑剔,请参见:https://unix.stackexchange.com/questions/181937/how-create-a-temporrary-file-in-shell-shell-script
另外,以脚本中的内容为例,从中写下您自己的perl单线(系统上的crc32
的存在表示已安装Perl和必要的模块(,或使用您使用Python One-Liner'已经找到了。
这是一个纯bash实现:
#!/usr/bin/env bash
declare -i -a CRC32_LOOKUP_TABLE
__generate_crc_lookup_table() {
local -i -r LSB_CRC32_POLY=0xEDB88320 # The CRC32 polynomal LSB order
local -i index byte lsb
for index in {0..255}; do
((byte = 255 - index))
for _ in {0..7}; do # 8-bit lsb shift
((lsb = byte & 0x01, byte = ((byte >> 1) & 0x7FFFFFFF) ^ (lsb == 0 ? LSB_CRC32_POLY : 0)))
done
((CRC32_LOOKUP_TABLE[index] = byte))
done
}
__generate_crc_lookup_table
typeset -r CRC32_LOOKUP_TABLE
crc32_string() {
[[ ${#} -eq 1 ]] || return
local -i i byte crc=0xFFFFFFFF index
for ((i = 0; i < ${#1}; i++)); do
byte=$(printf '%d' "'${1:i:1}") # Get byte value of character at i
((index = (crc ^ byte) & 0xFF, crc = (CRC32_LOOKUP_TABLE[index] ^ (crc >> 8)) & 0xFFFFFFFF))
done
echo $((crc ^ 0xFFFFFFFF))
}
printf 'The CRC32 of: %snis: %08xn' "${1}" "$(crc32_string "${1}")"
# crc32_string "The quick brown fox jumps over the lazy dog"
# yields 414fa339
测试:
bash ./crc32.sh "The quick brown fox jumps over the lazy dog"
The CRC32 of: The quick brown fox jumps over the lazy dog
is: 414fa339
您可以尝试使用rhash
。
- http://rhash.sourceforge.net/
- https://github.com/rhash/rhash
- http://manpages.ubuntu.com/manpages/bionic/man1/rhash.1.html
测试:
## install 'rhash'...
$ sudo apt-get install rhash
## test CRC32...
$ echo -n 123456789 | rhash --simple -
cbf43926 (stdin)