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?

Asked By: V_S

||

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')
Answered By: blhsing

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)
Answered By: 0x0fba
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.