I have hundreds of entries on hundreds of files that look like this (numbers not fixed):
"DstQuad":[12,-36,27,-36,27,-23,12,-23],"SrcQuad":[493,95,508,95,508,108,493,108]
The relevant portion of the files look like this, repeated hundreds of times, with no lines, just a continuous string:
{"TexID":0,"DstQuad":[-24,-23,-1,-23,-1,6,-24,6],"SrcQuad":[61,240,84,240,84,269,61,269]},{"TexID":0,"DstQuad":[-11,-73,36,-73,36,-45,-11,-45],"SrcQuad":[87,240,134,240,134,268,87,268]},
I need to be able to tell when a number is inside that structure, then take each number and multiply it, while leaving numbers not in that structure alone.
Tried adapting a script I found, but it doesn't do anything:
def multiply_numbers_in_context(match):
# return "{0}{1}{2}".format(match.group(1), str(float(match.group(2))*4), '"')
return "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}{16}".format(match.group(1), str(int(match.group(2))*4), ',', str(int(match.group(3))*4), ',', str(int(match.group(4))*4), ',', str(int(match.group(5))*4), ',', str(int(match.group(6))*4), ',', str(int(match.group(7))*4), ',', str(int(match.group(8))*4), ',', str(int(match.group(9))*4), ',', match.group(10), ',', str(int(match.group(11))*4), ',', str(int(match.group(12))*4), ',', str(int(match.group(13))*4), ',', str(int(match.group(14))*4), ',', str(int(match.group(15))*4), ',', str(int(match.group(16))*4), ']')
editor.rereplace(r'("DstQuad":[)(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d )(],"SrcQuad":[)(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d )(])', multiply_numbers_in_context)
Help would be greatly appreciated.
CodePudding user response:
I'd suggest using the json
module for this. Here's a simple example with loading a JSON string and using object_hook
to multiply each list element by a constant value (4 in this case). The result string
is a JSON string that can then be saved to a file.
I also made a few assumptions about your use case:
- The contents of the file can be represented as a list
[]
that contains a bunch of dictionaries{}
with the useful data - All nested lists
[]
that contain numbers should have all their elements multipled by a constant value (of 4 in this case)
import json
file_contents = """
[
{"TexID":0,"DstQuad":[-24,-23,-1,-23,-1,6,-24,6],"SrcQuad":[61,240,84,240,84,269,61,269]},
{"TexID":0,"DstQuad":[-11,-73,36,-73,36,-45,-11,-45],"SrcQuad":[87,240,134,240,134,268,87,268]}
]
"""
def hook_fn(value, multiplier=4):
if isinstance(value, list) and value and isinstance(value[0], (int, float)):
return [elem * multiplier for elem in value]
if isinstance(value, dict):
return {k: hook_fn(v) for k, v in value.items()}
return value
string = json.dumps(json.loads(file_contents, object_hook=hook_fn))
print(string)
# [{"TexID": 0, "DstQuad": [-96, -92, -4, -92, -4, 24, -96, 24], "SrcQuad": [244, 960, 336, 960, 336, 1076, 244, 1076]}, {"TexID": 0, "DstQuad": [-44, -292, 144, -292, 144, -180, -44, -180], "SrcQuad": [348, 960, 536, 960, 536, 1072, 348, 1072]}]
To read and write from a text file instead, use json.load
and json.dump
instead (drop the s
at the end):
with open('input.txt') as in_file:
data = json.load(in_file, object_hook=hook_fn)
with open('output.txt', 'w') as out_file:
json.dump(data, out_file)