How to change a string name in a file when a hexadecimal numbers is split?
Question:
I have a file named input.txt
.
name="XYZ_PP_0" number="0x12" bytesize="4" info="0x00000012"
name="GK_LMP_2_0" number="0xA5" bytesize="8" info="0x00000000bbae321f"
name="MP_LKO_1_0" number="0x356" bytesize="4" info="0x00000234"
name="PNP_VXU_1_2_0" number="0x48A" bytesize="8" info="0x00000000a18c3ba3"
name="AVU_W_2_3_1" number="0x867" bytesize="1" info="0x0b"
From this file i need to create another file output.txt
. in this file if bytesize="8"
then info
is split in to two.
eg:
number="0x48A" bytesize="8" info="0x00000000a18c3ba3"
then output file will contain:
name="PNP_VXU_1_2_0_LOW" number="0x48A" info="0xa18c3ba3"
name="PNP_VXU_1_2_0_HIGH" number="0x4BC" info="0x00000000"
where 0x4BC = 0x48A + 0x32
this is current code:
import re
infile_path = "./input.txt"
outfile_path = "./output.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')
output.txt
for this code:
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="0x867" info="0x0b"
Expected Output:
name="XYZ_PP_0" number="0x12" info="0x00000012"
name="GK_LMP_2_0_LOW" number="0xA5" info="0xbbae321f"
name="GK_LMP_2_0_HIGH"number="0xD7" info="0x00000000"
name="MP_LKO_1_0" number="0x356" info="0x00000234"
name="PNP_VXU_1_2_0_LOW" number="0x48A" info="0xa18c3ba3"
name="PNP_VXU_1_2_0_HIGH" number="0x4BC" info="0x00000000"
name="AVU_W_2_3_1" number="0x867" info="0x0b"
How can i add the LOW and HIGH to the name if byte size is 8?
Answers:
With your current code you just need to capture the name with the regex and add it to the output in the same way you handle nums
:
with open(infile_path, "r") as infile, open(outfile_path, "w") as outfile:
for s in infile:
r = re.match('name="(.*)" number="(.*)" bytesize="(.*)" info="(.*)"', s)
if r:
name, *numbers = r.groups()
num, bs, info = map(lambda x: int(x, 0), numbers)
l = len(r.group(3)) - 2
if bs == 8:
l = 8
names = (f'{name}_LOW', f'{name}_HIGH')
nums = (num, num + 0x32)
infos = (info % (2**32), info // (2**32))
else:
names = (name, )
nums = (num, )
infos = (info, )
for name, num, info in zip(names, nums, infos):
outfile.write(f'name="{name}" number="{num:#x}" info="{info:#0{l+2}x}"n')
The regex is compiled at the beginning to improve performance.
The process()
function analyzes an input line and writes to the output file.
PATTERN = re.compile(r'(w*)="([^"]*)')
def process(line, f_out):
name, number, bytesize, info = [x[1] for x in PATTERN.findall(line)]
if int(bytesize) == 8:
n = int(number, 16) + 0x32
f_out.writelines(
[
f'name="{name}_LOW" number="{number}" info="0x{info[-8:]}"n',
f'name="{name}_HIGH" number="0x{n:02X}" info="{info[:10]}"n'
]
)
else:
f_out.writelines(line)
with open("input.txt") as f_in, open("output.txt", "w") as f_out:
for line in f_in:
process(line, f_out)
I have a file named input.txt
.
name="XYZ_PP_0" number="0x12" bytesize="4" info="0x00000012"
name="GK_LMP_2_0" number="0xA5" bytesize="8" info="0x00000000bbae321f"
name="MP_LKO_1_0" number="0x356" bytesize="4" info="0x00000234"
name="PNP_VXU_1_2_0" number="0x48A" bytesize="8" info="0x00000000a18c3ba3"
name="AVU_W_2_3_1" number="0x867" bytesize="1" info="0x0b"
From this file i need to create another file output.txt
. in this file if bytesize="8"
then info
is split in to two.
eg:
number="0x48A" bytesize="8" info="0x00000000a18c3ba3"
then output file will contain:
name="PNP_VXU_1_2_0_LOW" number="0x48A" info="0xa18c3ba3"
name="PNP_VXU_1_2_0_HIGH" number="0x4BC" info="0x00000000"
where 0x4BC = 0x48A + 0x32
this is current code:
import re
infile_path = "./input.txt"
outfile_path = "./output.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')
output.txt
for this code:
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="0x867" info="0x0b"
Expected Output:
name="XYZ_PP_0" number="0x12" info="0x00000012"
name="GK_LMP_2_0_LOW" number="0xA5" info="0xbbae321f"
name="GK_LMP_2_0_HIGH"number="0xD7" info="0x00000000"
name="MP_LKO_1_0" number="0x356" info="0x00000234"
name="PNP_VXU_1_2_0_LOW" number="0x48A" info="0xa18c3ba3"
name="PNP_VXU_1_2_0_HIGH" number="0x4BC" info="0x00000000"
name="AVU_W_2_3_1" number="0x867" info="0x0b"
How can i add the LOW and HIGH to the name if byte size is 8?
With your current code you just need to capture the name with the regex and add it to the output in the same way you handle nums
:
with open(infile_path, "r") as infile, open(outfile_path, "w") as outfile:
for s in infile:
r = re.match('name="(.*)" number="(.*)" bytesize="(.*)" info="(.*)"', s)
if r:
name, *numbers = r.groups()
num, bs, info = map(lambda x: int(x, 0), numbers)
l = len(r.group(3)) - 2
if bs == 8:
l = 8
names = (f'{name}_LOW', f'{name}_HIGH')
nums = (num, num + 0x32)
infos = (info % (2**32), info // (2**32))
else:
names = (name, )
nums = (num, )
infos = (info, )
for name, num, info in zip(names, nums, infos):
outfile.write(f'name="{name}" number="{num:#x}" info="{info:#0{l+2}x}"n')
The regex is compiled at the beginning to improve performance.
The process()
function analyzes an input line and writes to the output file.
PATTERN = re.compile(r'(w*)="([^"]*)')
def process(line, f_out):
name, number, bytesize, info = [x[1] for x in PATTERN.findall(line)]
if int(bytesize) == 8:
n = int(number, 16) + 0x32
f_out.writelines(
[
f'name="{name}_LOW" number="{number}" info="0x{info[-8:]}"n',
f'name="{name}_HIGH" number="0x{n:02X}" info="{info[:10]}"n'
]
)
else:
f_out.writelines(line)
with open("input.txt") as f_in, open("output.txt", "w") as f_out:
for line in f_in:
process(line, f_out)