#1

#1

我有二进制数据,我以xxd -ps十六进制格式查看。我注意到分隔符为 的两个标头之间的字节距离为 48300 (=805*60) 字节fafafafa。文件的开头部分应该被跳过。

示例十六进制数据,其中标题 fafafafa 之间有 48300 字节,您可以获得这里被称为数据26.6.2015.txt其中三个标头及其几乎等效的二进制文件这里被称为test_27.6.2015.bin它只有前两个标头。在这两个文件中,最后一个头的数据都不是完整的长度;否则,您可以假设字节偏移量是固定的,即标头之间的数据长度。

算法伪代码

  1. 查看标题结束位置
  2. 查看前两个标题位置并设置这些位置的差异(d2 - d1) 事件之间的距离;该事件长度是固定的 (777)
  3. 按字节位置分割数据 (777) - TODO 我应该分割二进制格式还是xxd -ps转换后的数据?按字节位置 (777)

xxd -r我可以通过类似方式将数据转换回二进制xxd -ps | split and store | xxd -r,但我仍然不确定这是否有必要。

在哪个阶段可以分割二进制数据?仅采用xxd -ps转换后的格式或二进制数据。

如果以xxd -ps转换后的格式分割,我认为 for 循环是遍历文件的唯一方法。可能的拆分工具csplitsplit...,不确定。然而,我不确定。

grep(ggrep 是 gnu grep)对十六进制数据的输出

$ xxd -ps r328.raw  | ggrep -b -a -o -P 'fafa' | head
49393:fafa
49397:fafa
98502:fafa
98506:fafa
147611:fafa
147615:fafa
196720:fafa
196725:fafa
245830:fafa
245834:fafa

在二进制文件中执行类似的 grep 时,仅将空行作为输出。

$ ggrep -b -a -o '\xfa' r328.raw 

文档

找到了给我的文档这里下图是一般 SRS 数据格式:

在此输入图像描述

您可以在哪个阶段拆分二进制数据(作为二进制数据或xxd -ps转换后的数据)?

答案1

可以对二进制文件进行操作,无需经过xxd。我通过 xxd 跑回了你的数据并用来grep -b向我展示字节偏移量\xfa二进制文件中的模式(从 hex 转换为 chars )。

sed从输出中删除了匹配的字符,只留下数字。然后,我将 shell 位置参数设置为结果偏移量 ( set --...)

xxd -r -p <data26.6.2015.txt >/tmp/f1
set -- $(grep -b -a -o -P '\xfa\xfa\xfa\xfa' /tmp/f1 | sed 's/:.*//')

现在,您在 $1、$2、... 中有一个偏移量列表,然后您可以使用 dd 提取您感兴趣的部分,将块大小设置为 1 ( bs=1),以便它逐字节读取。skip=表示输入中要跳过多少字节,以及count=要复制的字节数。

start=$1 end=$2
let count=$end-$start
dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f2

上面从第一个模式的开始到第二个模式之前提取。要不包含该模式,您可以在开始时添加 4(计数会减少 4)。

如果要提取所有部分,请使用同一代码的循环,并将起始偏移量 0 和结束偏移量文件大小添加到数字列表中:

xxd -r -p <data26.6.2015.txt >/tmp/f1
size=$(stat -c '%s' /tmp/f1)
set -- 0 $(grep -b -a -o -P '\xfa\xfa\xfa\xfa' /tmp/f1 | sed 's/:.*//') $size
i=2
while [ $# -ge 2 ]
do start=$1 end=$2
   let count=$end-$start
   dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f$i
   let i=i+1
   shift
done

如果 grep 无法处理二进制数据,您可以使用 xxd 十六进制转储数据。首先删除所有换行符以获得一大行,然后使用未转义的十六进制值执行 grep,然后将所有偏移量除以 2,并使用原始文件执行 dd:

xxd -r -p <data26.6.2015.txt >r328.raw
tr -d '\n' <data26.6.2015.txt >f1
let size2=2*$(stat -c '%s' f1)
set -- 0 $(grep -b -a -o -P 'fafafafa' f1 | sed 's/:.*//') $size2
i=2
while [ $# -ge 2 ]
do  let start=$1/2
    let end=$2/2
    let count=$end-$start
    dd bs=1 count=$count skip=$start <r328.raw  >f$i
    let i=i+1
    shift
done

答案2

输出到伟大的meuh回答他在哪里使用数据数据26.6.2015.txt

#1

$ cat 27.6.2015_1.sh && sh 27.6.2015_1.sh 
xxd -r -p <data26.6.2015.txt >/tmp/f1
size=$(stat -c '%s' /tmp/f1)
pat=$(echo -e '\xfa\xfa\xfa\xfa')
set -- 0 $(ggrep -b -a -o "$pat" /tmp/f1 | sed 's/:.*//') $size
i=2
while [ $# -ge 2 ]
do start=$1 end=$2
   let count=$end-$start
   dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f$i
   let i=i+1
   shift
done
72900+0 records in
72900+0 records out
72900 bytes (73 kB) copied, 0.160722 s, 454 kB/s

#2

$ cat 27.6.2015_2.sh && sh 27.6.2015_2.sh 
xxd -r -p <data26.6.2015.txt >/tmp/f1
size=$(stat -c '%s' /tmp/f1)
set -- 0 $(ggrep -b -a -o -P '\xfa\xfa\xfa\xfa' /tmp/f1 | sed 's/:.*//') $size
i=2
while [ $# -ge 2 ]
do start=$1 end=$2
   let count=$end-$start
   dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f$i
   let i=i+1
   shift
done
72900+0 records in
72900+0 records out
72900 bytes (73 kB) copied, 0.147935 s, 493 kB/s

#3

$ cat 27.6.2015_3.sh && sh 27.6.2015_3.sh 
xxd -r -p <data26.6.2015.txt >r328.raw
tr -d '\n' <data26.6.2015.txt >f1
let size2=2*$(stat -c '%s' f1)
set -- 0 $(ggrep -b -a -o -P 'fafafafa' f1 | sed 's/:.*//') $size2
i=2
while [ $# -ge 2 ]
do  let start=$1/2
    let end=$2/2
    let count=$end-$start
    dd bs=1 count=$count skip=$start <r328.raw  >f$i
    let i=i+1
    shift
done
24292+0 records in
24292+0 records out
24292 bytes (24 kB) copied, 0.088345 s, 275 kB/s
24152+0 records in
24152+0 records out
24152 bytes (24 kB) copied, 0.061246 s, 394 kB/s
24152+0 records in
24152+0 records out
24152 bytes (24 kB) copied, 0.058611 s, 412 kB/s
304+0 records in
304+0 records out
304 bytes (304 B) copied, 0.001239 s, 245 kB/s

输出是 1 个十六进制文件和 4 个二进制文件:

$ less f1
$ less f2
"f2" may be a binary file.  See it anyway? 
$ less f3
"f3" may be a binary file.  See it anyway? 
$ less f4
"f4" may be a binary file.  See it anyway? 
$ less f5
"f5" may be a binary file.  See it anyway? 

应该只有 3 个包含 fafafafa 的文件,因为我只在文件 data26.6.2015.txt 中给出了三个标头,其中最后一个标头的内容是存根。 f2-f5 中的输出:

$ xxd -ps f2 |head -n3
48000000fe5a1eda480000000d00030001000000cd010000010000000000
000000000000000000000000000000000000000000000100000001000000
ffffffff57ea5e5580510b0048000000fe5a1eda480000000d0003000100
$ xxd -ps f3 |head -n3
fafafafa585e0000fe5a1eda480000000d00030007000000cd0100000200
000000000000020000000000008000000000000000000000000000000000
01000000ffffffff72ea5e55b2eb0900105e000016000000010000000000
$ xxd -ps f4 |head -n3
fafafafa585e0000fe5a1eda480000000d00030007000000cd0100000300
000000000000020000000000008000000000000000000000000000000000
01000000ffffffff72ea5e55f2ef0900105e000016000000010000000000
$ xxd -ps f5 |head -n3
fafafafa585e0000fe5a1eda480000000d00030007000000cd0100000400
000000000000020000000000008000000000000000000000000000000000
01000000ffffffff72ea5e55a9f10900105e000016000000010000000000

在哪里

  • f1 是整个数据文件数据26.6.2015.txt(不必包含)
  • f2 是文件头,即文件的开头数据26.6.2015.txt直到第一个标题发发发发(不必包含)
  • f3 是第一个标头,正确!
  • f4 是第二个标头,正确!
  • f5 是第三个标头,正确!

答案3

这并不难:只需查找起始字符串,命名并匹配尾部字符串即可。否则,至少尝试靠近。您实际上并不需要所有十六进制,但使用它:

fold -w2 <hexfile |
sed -e:t -e's/[[:xdigit:]]\{2\}$/\\x&/
    /f[af]$/N;/\(.\)..\1$/!s/.*\n/&\\x/;t
    /^.*\(.\)\(\n.*\)\n\(.*\n\).*/!bt
    s//\3\3\3 H_E_A_D \1 E_N_D \2\2\2/
    s/.* f//;s/a E.*//'

这将在每行获得一个十六进制字节码 - 每个前缀为 w/ \x- 对于每个字节hexfile 除了其中字节码faff依次出现 4 次。在这种情况下,它将得到一个H_E_A_D或者E_N_D相反,标记,其中H_E_A_D字符串将替换四个字符串中的最后一个\xfa,并且E_N_Dstring 将替换四个连续字符串中的第一个\xff- 这也应该使字节偏移量按行号保持同步。

像这样:

PIPELINE | grep -C8n _

输出:

(稍微修剪一下)

72596-\x8b
72597-\xfa
72598-\xfa
72599-\xfa
72600:H_E_A_D
72601-\x58
--
72660-\x00
72661:E_N_D
72662-\xff
72663-\xff
72664-\xff
72665-\x72

因此,您可以将上述命令的输出传递给,例如:

fold ... | sed ... | grep -n _

...获取标头可能开始、结束的偏移列表。对于 GNU,grep您可以使用-After 开关来告诉它您希望在上下文序列中看到多少字节 - 例如,您可能想使用-A777。您可以获取这样的输出并将其传递:

... | grep -A777 E_N_D | sed -ne's/\\/&&/p' | xargs printf %b

...为每个序列重现每个二进制字节,并且可以指定匹配号 w/ -m[num]

相关内容