我很久以前用crc32计算了stc的校验栏,但我不记得是怎么做的。
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] How to calculate CRC32 with Python to match online results?
答案 0 :(得分:10)
我自己遇到了这个问题,我不想去安装crc32
的“麻烦”。我想出了这个,虽然它有点讨厌,它应该适用于大多数平台,或者大多数现代linux无论如何...
echo -n "LongString" | gzip -c | tail -c8 | hexdump -n4 -e '"%u"'
仅提供一些技术细节,gzip uses crc32在最后8个字节中,-c
选项使其输出到标准输出,tail
去掉最后8个字节。
hexdump
有点棘手,在我想出一些令人满意的东西之前我不得不用它一段时间,但这里的格式似乎正确地将gzip crc32解析为一个32位数字:
-n4
仅占用gzip页脚的相关前4个字节。'"%u"'
是您的标准fprintf格式字符串,它将字节格式化为单个无符号32位整数。 请注意,这里有单引号嵌套的双引号。如果需要十六进制校验和,可以将格式字符串更改为'"%08x"'
(或大写十六进制的'"%08X"'
),它将校验和格式化为8个字符(0填充)十六进制。
就像我说的那样,不是最优雅的解决方案,也许不是一种你想要在性能敏感的场景中使用的方法,而是一种可能会有吸引力的方法,因为所使用的命令几乎具有普遍性。
这里的跨平台可用性的弱点可能是hexdump
配置,因为我已经看到它从平台到平台的变化,而且它有点繁琐。我建议如果你使用它,你应该尝试一些测试值并与results of an online tool进行比较。
编辑正如@PedroGimeno在评论中所建议的那样,您可以将输出传输到od
而不是hexdump
,以获得相同的结果,而不需要繁琐的选项。 ... | od -t x4 -N 4 -A n
表示十进制... | od -t d4 -N 4 -A n
。
答案 1 :(得分:6)
至少在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-temporary-file-in-shell-script
或者,使用脚本中的内容作为编写自己的Perl单线程的示例(系统上存在crc32
表示已安装Perl和必要的模块),或使用Python你已经找到的单线。
答案 2 :(得分:6)
或仅使用流程替换:
crc32 <(echo "LongString")
答案 3 :(得分:3)
你的问题已经有了大部分答案。
echo -n 123456789 | python -c 'import sys;import zlib;print(zlib.crc32(sys.stdin.read())%(1<<32))'
正确地给出了3421780262
我更喜欢hex:
echo -n 123456789 | python -c 'import sys;import zlib;print("%08x"%(zlib.crc32(sys.stdin.read())%(1<<32)))'
cbf43926
请注意,有几种CRC-32算法: new Seleniums IDE
答案 4 :(得分:2)
我使用cksum
并使用内置printf
的shell转换为十六进制:
$ echo -n "LongString" | cksum | cut -d\ -f1 | xargs echo printf '%0X\\n' | sh
5751BDB2
答案 5 :(得分:0)
这是一个纯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
测试:
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