使用 bash 将二进制文件中的单个字节提取到变量中

Min*_*666 10 bash shell-script binary serial-port

我需要制作一个相当简单的 bash 脚本,一次从二进制文件中提取一个字节,将其发送到串行端口,然后等待一个字节返回,然后再发送下一个。这对于 EEPROM 编程器非常有效,在这种情况下,现成的解决方案将不起作用。

我主要是把字节从文件中提取到一个变量中,除此之外我知道我可以通过串行端口回显这些值并用 dd 读回它们。(有没有更好的方法来做到这一点?)

谢谢您的帮助!

ken*_*orb 11

使用ddxxd(Vim 的一部分),例如从二进制文件中读取-l偏移量 100 ( -s)处的一个字节 ( )尝试:

xxd -p -l1 -s 100 file.bin
Run Code Online (Sandbox Code Playgroud)

要使用十六进制偏移量,在 Bash 中您可以使用此语法$((16#64)),例如:

echo $((16#$(xxd -p -l1 -s $((16#FC)) file.bin)))
Run Code Online (Sandbox Code Playgroud)

它在偏移处读取字节FC并以十进制格式打印。

或者使用dd,例如:

dd if=file.bin seek=$((16#FC)) bs=1 count=5 status=none
Run Code Online (Sandbox Code Playgroud)

它将以十六进制偏移量转储 5 个字节的原始数据FC

然后你可以将它分配给变量,但是当你的数据有 NULL bytes 时不起作用,因此你可以跳过它们 ( xxd -a) 或者作为解决方法,你可以以纯十六进制格式存储它们。

例如:

  1. 将偏移量 10 处的 10 个字节读入包含十六进制格式字节的变量:

    hex=$(xxd -p -l 10 -s 10 file.bin)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后将它们写入文件或设备:

    xxd -r -p > out.bin <<<$hex
    
    Run Code Online (Sandbox Code Playgroud)

以下是 Bash 中一些有用的函数:

set -e

# Read single decimal value at given offset from the file.
read_value() {
  file="$1"
  offset="$2"
  [ -n "$file" ]
  [ -n "$offset" ]
  echo $((16#$(xxd -p -l1 -s $offset "$file")))
}

# Read bytes in hex format at given offset from the file.
read_data() {
  file="$1"
  offset="$2"
  count="$3:-1"
  xxd -p -l $count -s $offset "$file"
}
Run Code Online (Sandbox Code Playgroud)

示例用法:

read_value file.bin $((16#FC)) # Read 0xFC offset from file.bin.
Run Code Online (Sandbox Code Playgroud)


cuo*_*glm 0

您可以使用perl

\n\n
$ printf \'%s%s%s\' \'\xc4\x83\xc3\xa2\xc3\xa9\' | LC_ALL=C.UTF-8 perl -Mopen=locale -ne \'\n    BEGIN { $/ = \\1 }\n    printf "%s\\n", $_;\n\'\n\xc4\x83\n\xc3\xa2\n\xc3\xa9\n
Run Code Online (Sandbox Code Playgroud)\n