如何在特定条件下拆分文本文件中的十六进制数字?



我有一个名为output的文件.txt它包含以下数据。

number="0x12" bytesize="4" info="0x00000012"
number="0xA5" bytesize="8" info="0x00000000bbae321f"
number="0x356" bytesize="4" info="0x00000234"
number="0x48A" bytesize="8" info="0x00000000a18c3ba3"
number="0x156" bytesize="2" info="0x001A"
number="0x867" bytesize="1" info="0x0b"

使用此文件,我需要创建另一个名为new的文件.txt其中,如果字节大小为8,则需要拆分数据,然后将其写入new.txt如果bytesized为1,2,4,则将数据直接写入new.txt。

例如:

number="0xA5" bytesize="8" info="0x00000000bbae321f"
number="0x48A" bytesize="8" info="0x00000000a18c3ba3"

这里的字节大小是 8,那么我需要将信息拆分为"0x00000000"和"0xbbae321f",并用新数字存储它们,如下所示

number="0xA5" info="0xbbae321f"
number="0xD7" info="0x00000000"
number="0x48A" info="0xa18c3ba3"
number="0x4BC" info="0x00000000"

其中,0xD7 = 0xA5 + 0x32,0x4BC = 0x48A + 0x32

所以最后new.txt应该是这样的:

number="0x12" info="0x00000012"
number="0xA5" info="0xbbae321f"
number="0xD7" info="0x00000000"
number="0x356" info="0x00000234"
number="0x48A" info="0xa18c3ba3"
number="0x4BC" info="0x00000000"
number="0x156" info="0x001A"
number="0x867" info="0x0b"

我只提供一个解决方案。

最重要的是从一行中获取bytesize项(和其他项)。我使用regular expression来做到这一点。

import re                                                     
infile_path = "./output.txt"  # adjust to your case
outfile_path = "./new.txt"
with open(infile_path, "r") as infile, open(outfile_path, "w") as outfile:
for s in infile:
r = re.match('number="(.*)" bytesize="(.*)" info="(.*)"', s)
if r:
num, bs, info = map(lambda x: int(x, 0), r.groups())
l = len(r.group(3)) - 2
if bs == 8:
l = 8
nums = (num, num + 0x32)
infos = (info % (2**32), info // (2**32))
else:
nums = (num, )
infos = (info, )
for num, info in zip(nums, infos):
outfile.write(f'number="{num:#x}" info="{info:#0{l+2}x}"n')

有很多方法可以做到这一点。分离出文件的解析,处理数据,写入数据似乎提供了最佳的灵活性。

numberbytesizeinfo值似乎是整数,因此如果将它们存储为整数,则检查bytesize操作变得容易。 它还使在将bytesize=8拆分为两个bytesize=4时可以轻松地将0x32添加到number中。

若要从info整数中查找两个 4 字节值,可以使用按位运算。

要找到较高的四个字节,将位向右移动 32 位将给出四个最高字节的值。

要查找最低的四个字节,请用给出最低四个字节的值来屏蔽四个最高字节。这可以通过按位&运算来完成。

下面的示例已经在 Python 3.10 中进行了测试,但应该适用于最新版本的 Python 3。

它使用数据类来存储数据的内部表示形式。

from dataclasses import dataclass
from pathlib import Path
import re
from typing import List, Tuple

@dataclass
class Data:
number: int
bytesize: int
info: int

def parse_file(filename: Path) -> List[Data]:
data = []
pattern = re.compile(
r'number="0x([0-9a-fA-F]+)"s+bytesize="(d+)"s+info="0x([0-9a-fA-F]+)"')
for line in filename.read_text().splitlines():
match = pattern.search(line)
if match:
data.append(Data(number=int(match.group(1), 16),
bytesize=int(match.group(2)),
info=int(match.group(3), 16))
)
return data

def two_size_four(entry: Data) -> Tuple[Data]:
data1 = Data(entry.number, 4, entry.info & 0xffffffff)
data2 = Data(entry.number + 0x32, 4, entry.info >> 4 * 8)
return data1, data2

def split_bytesize_8(data: List[Data]) -> List[Data]:
new_data = []
for entry in data:
if entry.bytesize != 8:
new_data.append(entry)
else:
split_data = two_size_four(entry)
new_data.extend(split_data)
return new_data

def writefile(filename: Path, data: List[Data]) -> None:
lines = []
for entry in data:
lines.append(
f'number="{entry.number:#x}" '
f'info="{entry.info:#0{entry.bytesize * 2 + 2}x}"')
output_txt = "n".join(lines)
print(output_txt)
filename.write_text(output_txt)

def main(filename_in: Path, filename_out: Path) -> None:
data = parse_file(filename_in)
data = split_bytesize_8(data)
writefile(filename_out, data)

if __name__ == '__main__':
input_file = Path(__file__).parent.joinpath("data", "output.txt")
output_file = Path(__file__).parent.joinpath("data", "new.txt")
main(input_file, output_file)

如果您运行的是 3.7 之前的 Python 版本,则可以在不使用dataclasses的情况下创建Data类,如下所示:

class Data:
def __init__(self, number: int, bytesize: int, info: int):
self.number = number
self.bytesize = bytesize
self.info = info

所有其他代码应相同

最新更新