如何在LinuxBash上从字符串计算crc32校验和
很久以前,我使用crc32从字符串计算校验和,但我不记得我是如何做到的如何在LinuxBash上从字符串计算crc32校验和,bash,checksum,crc32,Bash,Checksum,Crc32,很久以前,我使用crc32从字符串计算校验和,但我不记得我是如何做到的 echo -n "LongString" | crc32 # no output 我找到了一个用Python计算它们的解决方案[1],但是没有直接的方法从字符串计算它们吗 # signed python -c 'import binascii; print binascii.crc32("LongString")' python -c 'import zlib; print z
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)'
#已签名
python-c’导入binascii;打印binascii.crc32(“LongString”)'
python-c’导入zlib;打印zlib.crc32(“长字符串”)'
#无符号
python-c’导入binascii;打印binascii.crc32(“长字符串”)%(1)至少在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
的过程置于后台,因为它将一直阻塞,直到下一个命令读取它
要更严格地创建临时文件,请参见:
或者,以脚本中的内容为例,编写自己的Perl one liner(系统中出现的crc32
表示安装了Perl和必要的模块),或者使用您已经找到的Python one liner。我自己也遇到了这个问题,我不想再“麻烦”了关于安装crc32
。我想到了这个,虽然有点讨厌,但它应该可以在大多数平台上工作,或者至少在大多数现代linux上工作
echo -n "LongString" | gzip -c | tail -c8 | hexdump -n4 -e '"%u"'
仅提供一些技术细节,在最后8个字节中,-c
选项使其输出为标准输出,tail
去掉最后8个字节
hextump
有点棘手,我不得不花了一段时间才想出令人满意的方法,但这里的格式似乎正确地将gzip crc32解析为单个32位数字:
-n4
仅获取gzip页脚的相关前4个字节
““%u”
是您的标准fprintf格式字符串,它将字节格式化为单个无符号32位整数。请注意,此处有双引号嵌套在单引号中
如果需要十六进制校验和,可以将格式字符串更改为'%08x'
(或'%08x'
大写十六进制),将校验和格式化为8个字符(0填充)的十六进制
正如我所说,这不是最优雅的解决方案,也可能不是您希望在性能敏感的场景中使用的方法,而是一种考虑到所使用命令的普遍性而可能具有吸引力的方法
跨平台可用性的弱点可能是hextump
配置,因为我看到它在不同平台上的变化,而且有点复杂。我建议如果您使用它,您应该尝试一些测试值,并与
编辑正如@PedroGimeno在评论中所建议的那样,您可以将输出导入od
而不是hextdump
,以获得相同的结果,而无需复杂的选项。对于十六进制,od-tx4-n4-ann
。您的问题已经有了大部分答案。
echo -n 123456789 | python -c 'import sys;import zlib;print(zlib.crc32(sys.stdin.read())%(1<<32))'
请注意,有几种CRC-32算法:
或仅使用流程替换:
crc32 <(echo "LongString")
crc32这里是一个纯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: %s\nis: %08x\n' "${1}" "$(crc32_string "${1}")"
# crc32_string "The quick brown fox jumps over the lazy dog"
# yields 414fa339
我使用cksum
并使用shell内置printf
转换为十六进制:
$ echo -n "LongString" | cksum | cut -d\ -f1 | xargs echo printf '%0X\\n' | sh
5751BDB2
对于十六进制,一个更便携的解决方案是使用而不是hextdump:。| od-tx4-n4-ann
可以确认这是一种享受!-tx4
用于十六进制输出,而-td4
用于十进制输出。这也可以通过为您处理FIFO来实现:crc32我一直在寻找它也可以使用pv。它将文件输出为st生成进度条时响铃。crc32如果希望管道从左向右,可以执行echo-n“LongString”| crc32/dev/stdin
/dev/stdin是一个包含流程输入的特殊文件。有趣的是,这里列出的所有管道都没有使用“ZIP”聚EDB88320@silverdr这里列出的所有带有poly=0x04c11db7
和refin=true
do.CRC-32/ISO-HDLC的都是PKZIP-CRC。我肯定在这里遗漏了一些明显的东西,但是poly=0x04c11db7
如何意味着使用edb88320
?我想这与refin=true
有关uestion当我在寻找调整校验和例程所需的定义时,发现(对我)有冲突信息。最终使用edb88320
和起始种子ffffffff
和最终ffffffff
EOR获得与所述crc32
脚本输出兼容的结果。@silverdr0xedb88320
是0x04c11db7
的位反转refin=true
表示输入位被反射。在实践中,这是永远不会发生的,因为你必须对每个输入字节进行反射。相反,多项式被反射一次。我必须使用cut-d”“-f1
而不是cut-d \-f1
(因此在这里修剪两个空格中的一个),否则它只会给出一个错误。
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
$ echo -n "LongString" | cksum | cut -d\ -f1 | xargs echo printf '%0X\\n' | sh
5751BDB2