如何在LinuxBash上从字符串计算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

很久以前,我使用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)'
#已签名
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
脚本输出兼容的结果。@silverdr
0xedb88320
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