如何从linux bash上的字符串计算crc32校验和

oxi*_*rks 5 bash crc32 checksum

我很久以前用crc32计算了stc的校验栏,但我不记得我是怎么做的.

echo -n "LongString" | crc32    # no output
Run Code Online (Sandbox Code Playgroud)

我找到了一个用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)'
Run Code Online (Sandbox Code Playgroud)

[1] 如何使用Python计算CRC32以匹配在线结果?

rob*_*ert 12

我自己遇到了这个问题,我不想去安装的"麻烦" crc32.我想出了这个,虽然它有点讨厌它应该适用于大多数平台,或者大多数现代的linux ...

echo -n "LongString" | gzip -c | tail -c8 | hexdump -n4 -e '"%u"'
Run Code Online (Sandbox Code Playgroud)

为了提供一些技术细节,gzip在最后8个字节中使用crc32,该-c选项使它输出到标准输出并tail去除最后8个字节.

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十六进制... | od -t d4 -N 4 -A n为十进制.

  • 一个更便携的十六进制解决方案是使用[od](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/od.html)而不是hexdump:`... | od -t x4 -N 4 -A n` (2认同)
  • 使用“gzip -1 -c”可以使压缩速度更快,因为无论如何你都会扔掉它。 (2认同)

C W*_*rtz 12

或者只是使用流程替换:

crc32 <(echo "LongString")
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望管道从左到右,您可以执行 `echo -n "LongString" | crc32 /dev/stdin`。/dev/stdin 是一个特殊文件,包含进程的输入。 (3认同)

Mar*_*ler 8

Your question already has most of the answer.

echo -n 123456789 | python -c 'import sys;import zlib;print(zlib.crc32(sys.stdin.read())%(1<<32))'
Run Code Online (Sandbox Code Playgroud)

correctly gives 3421780262

I prefer hex:

echo -n 123456789 | python -c 'import sys;import zlib;print("%08x"%(zlib.crc32(sys.stdin.read())%(1<<32)))'
cbf43926
Run Code Online (Sandbox Code Playgroud)

Be aware that there are several CRC-32 algorithms: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.32


Léa*_*ris 7

这是一个纯 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
Run Code Online (Sandbox Code Playgroud)

测试:

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
Run Code Online (Sandbox Code Playgroud)

为了荣耀起见,这里有一个 POSIX shell 语法版本:

由于 POSIX shell 没有表,因此它使用硬编码的多项式参数列表。

#!/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
Run Code Online (Sandbox Code Playgroud)


sli*_*lim 6

至少在Ubuntu上/usr/bin/crc32是一个简短的Perl脚本,你可以从它的源代码中清楚地看到它可以做的就是打开文件.它无法从stdin读取 - 它没有特殊的处理方式,-如文件名,-c参数或类似的东西.

因此,最简单的方法是使用它,并制作一个临时文件.

tmpfile=$(mktemp)
echo -n "LongString" > "$tmpfile"
crc32 "$tmpfile"
rm -f "$tmpfile"
Run Code Online (Sandbox Code Playgroud)

如果你真的不想写一个文件(比如你的文件系统可以采用更多的数据 - 不太可能,如果它真的是一个"长字符串",但是为了参数......)你可以使用命名管道.对于一个简单的非随机访问阅读器,这与文件无法区分:

fifo=$(mktemp -u)
mkfifo "$fifo"
echo -n "LongString" > "$fifo" &
crc32 "$fifo"
rm -f "$fifo"
Run Code Online (Sandbox Code Playgroud)

请注意&写入的进程的后台fifo,因为它将阻塞直到下一个命令读取它.

有关临时文件创建的更加挑剔,请参阅:https: //unix.stackexchange.com/questions/181937/how-create-a-temporary-file-in-shell-script


或者,使用脚本中的内容作为编写自己的Perl单线程的示例(crc32系统上存在指示Perl和必要的模块已安装),或使用您已经找到的Python单行程序.


jim*_*mis 5

我使用cksumshell 内置命令并转换为十六进制printf

$ echo -n "LongString"  | cksum | cut -d\  -f1 | xargs echo printf '%0X\\n' | sh
5751BDB2
Run Code Online (Sandbox Code Playgroud)