将带有地址、字节值和注释的文本文件解析为二进制文件

将带有地址、字节值和注释的文本文件解析为二进制文件

我尝试从以下形式的文件开始:

00: 42 ; byte 0 is 0x42 / d
01: 52 ; byte 1 is 0x52 / r
02: 62 ; byte 2 is 0x62 / D
03: 72 ; byte 3 is 0x72 / R
07: 1f ; bytes 03..0e are implicitly 00, byte 0f is 0x1f

并用它生成一个 8 字节文件,其值(十六进制形式)为:

42 52 62 72 00 00 00 1f

确切的输入格式并不是一成不变的。我刚刚选择了“;”作为注释分隔符,因为它是单个字符且明确。根据传统,偏移量:和两位十六进制值的形式似乎很明显。

我怀疑最终的解决方案涉及使用sedawk删除注释,然后将它们的输出通过管道传输到xxd,但到目前为止,我的第一个实验已经失败了,我什至无法让 xxd 解析应该是最好的情况简单的文本文件。


对于我的第一次尝试,我简化了 config.src:

00: 42
01: 52
02: 62
03: 72

(暂时省略注释和隐含的零字节,并坚持使用与可打印 ASCII 相对应的值)

...然后尝试从中生成二进制文件:

xxd -r config.src config.bin

cat config.bin我期望从和看到什么xxd config.bin

BRbr00000000: 42 52 62 72 BRbr

我最终得到的是:

无法呈现包含不可打印内容的 2 字节文件cat,并且以下输出xxd config.bin00000000: 0301

所以...问题#1...我对 xxd 做错了什么,我该如何解决它(或者有更好的方法)?请记住,我确实想为每行指定一个字节值,并且非常希望能够自动跳过连续值并自动用零填充它们。

问题#2...一旦我让 xxd 解析我的文件,我怎样才能添加注释并在 xxd 看到它们之前将它们删除?

请注意,我本身并不打算使用 xxd...但这是一个共享网络服务器,我没有 root 或管理员访问权限,所以apt-get install不是一个选项,并且从源代码编译我自己的副本也不会'不一定很容易)。


(背景信息......对于解决问题来说并不是必需的,但可以添加背景信息来说明我为什么要这样做)

我正在开发基于 Arduino 的 IoT 控制器。在过去的几周里,它的配置由硬编码值和我每隔几天重新调整用途的 DIP 开关的各种解释组成。越来越乏味了。我还没有心情实现一个合适的 UI,所以我想到了让它从我的 Web 服务器获取二进制配置 blob 到 char[] 中作为启动时的第一个动作(使我能够调整运行时配置值,而不必一路刷新板本身,这在这一点上确实是一种痛苦)。

答案1

让我们从你的开始config.src

$ cat config.src
00: 42 ; byte 0 is 0x42 / d
01: 52 ; byte 1 is 0x52 / r
02: 62 ; byte 2 is 0x62 / D
03: 72 ; byte 3 is 0x72 / R
07: 1f ; bytes 03..0e are implicitly 00, byte 0f is 0x1f

将其转换为config.bin,注释被跳过-c1

$ xxd -r -c1 config.src config.bin
$ xxd config.bin
00000000: 4252 6272 0000 001f                      BRbr....

将其转换回以下config.src格式:

$ xxd -c1 config.bin # this is unmodified
00000000: 42  B
00000001: 52  R
00000002: 62  b
00000003: 72  r
00000004: 00  .
00000005: 00  .
00000006: 00  .
00000007: 1f  .
$ xxd -c1 config.bin | awk -F '' '
  {
    $0=substr($0, 7)    # remove 6 leading characters
    $0=substr($0, 1, 6) # remove ASCII output
  }
  /00$/{ next }      # skip hex 00
  { print $0 " ; " } # print line and empty comment
'
00: 42 ;
01: 52 ;
02: 62 ;
03: 72 ;
07: 1f ;

答案2

您可能想尝试 perl 的pack功能。

前任。给定

$ cat config.src
00: 42 ; byte 0 is 0x42 / d
01: 52 ; byte 1 is 0x52 / r
02: 62 ; byte 2 is 0x62 / D
03: 72 ; byte 3 is 0x72 / R
07: 1f ; bytes 03..0e are implicitly 00, byte 0f is 0x1f

然后

$ perl -ne 'm/(\d+): ([[:xdigit:]]{2})/; while($n++ < $1){print pack("x")}; print pack("H*",$2)' config.src | xxd -c1
00000000: 42  B
00000001: 52  R
00000002: 62  b
00000003: 72  r
00000004: 00  .
00000005: 00  .
00000006: 00  .
00000007: 1f  .

相关内容