Reputation: 1675
I have a log file containing lines formatted as shown below. I want to parse the values right next to the substrings element=(string)
, time=(guint64)
and ts=(guint64)
and save them to a list that will contain separate lists for each line:
0:00:00.336212023 62327 0x55f5ca5174a0 TRACE GST_TRACER :0:: element-latency, element-id=(string)0x55f5ca532a60, element=(string)rawvideoparse0, src=(string)src, time=(guint64)852315, ts=(guint64)336203035;
0:00:00.336866520 62327 0x55f5ca5176d0 TRACE GST_TRACER :0:: element-latency, element-id=(string)0x55f5ca53f860, element=(string)nvh264enc0, src=(string)src, time=(guint64)6403181, ts=(guint64)336845676;
The final output would then look like: [['rawvideoparse0', 852315, 336203035], ['nvh264enc0', 6403181, 336845676]]
.
I should probably use Python's string split or partition methods to obtain the relevant parts in each line but I can't come up with a short solution that can be generalised for the values that I'm searching for. I also don't know how to deal with the fact that the values element
and time
are terminated with a comma whereas ts
is terminated with a semicolon (without writing separate conditional for the two cases). How can I achieve this using the string manipulation methods in Python?
Upvotes: 1
Views: 109
Reputation: 5226
Regex was meant for this:
lines = """
0:00:00.336212023 62327 0x55f5ca5174a0 TRACE GST_TRACER :0:: element-latency, element-id=(string)0x55f5ca532a60, element=(string)rawvideoparse0, src=(string)src, time=(guint64)852315, ts=(guint64)336203035;
0:00:00.336866520 62327 0x55f5ca5176d0 TRACE GST_TRACER :0:: element-latency, element-id=(string)0x55f5ca53f860, element=(string)nvh264enc0, src=(string)src, time=(guint64)6403181, ts=(guint64)336845676;
"""
import re
pattern = re.compile(".*element-id=\\(string\\)(?P<elt_id>.*), element=\\(string\\)(?P<elt>.*), src=\\(string\\)(?P<src>.*), time=\\(guint64\\)(?P<time>.*), ts=\\(guint64\\)(?P<ts>.*);")
for l in lines.splitlines():
match = pattern.match(l)
if match:
results = match.groupdict()
print(results)
yields the following dictionaries (notice that the captured groups have been named in the regex above using (?P<name>...)
, thats why we have these names) :
{'elt_id': '0x55f5ca532a60', 'elt': 'rawvideoparse0', 'src': 'src', 'time': '852315', 'ts': '336203035'}
{'elt_id': '0x55f5ca53f860', 'elt': 'nvh264enc0', 'src': 'src', 'time': '6403181', 'ts': '336845676'}
You can make this regex pattern even more generic, since all the elements share a common structure <name>=(<type>)<value>
:
pattern2 = re.compile("(?P<name>[^,;\s]*)=\\((?P<type>[^,;]*)\\)(?P<value>[^,;]*)")
for l in lines.splitlines():
all_interesting_items = pattern2.findall(l)
print(all_interesting_items)
it yields:
[]
[('element-id', 'string', '0x55f5ca532a60'), ('element', 'string', 'rawvideoparse0'), ('src', 'string', 'src'), ('time', 'guint64', '852315'), ('ts', 'guint64', '336203035')]
[('element-id', 'string', '0x55f5ca53f860'), ('element', 'string', 'nvh264enc0'), ('src', 'string', 'src'), ('time', 'guint64', '6403181'), ('ts', 'guint64', '336845676')]
Note that in all cases, https://regex101.com/ is your friend for debugging regex :)
Upvotes: 1
Reputation: 485
This is not the fastest solution, but this is probably how I would code it for readability.
# create empty list for output
list_final_output = []
# filter substrings
list_filter = ['element=(string)', 'time=(guint64)', 'ts=(guint64)']
# open the log file and read in the lines as a list of strings
with open('so_58272709.log', 'r') as f_log:
string_example = f_log.read().splitlines()
print(f'string_example: \n{string_example}\n')
# loop through each line in the list of strings
for each_line in string_example:
# split each line by comma
list_split_line = each_line.split(',')
# loop through each filter substring, include filter
filter_string = [x for x in list_split_line if (list_filter[0] in x
or list_filter[1] in x
or list_filter[2] in x
)]
# remove the substring
filter_string = [x.replace(list_filter[0], '') for x in filter_string]
filter_string = [x.replace(list_filter[1], '') for x in filter_string]
filter_string = [x.replace(list_filter[2], '') for x in filter_string]
# store results of each for-loop
list_final_output.append(filter_string)
# print final output
print(f'list_final_output: \n{list_final_output}\n')
Upvotes: 0
Reputation: 15384
Here is a possible solution using a series of split commands:
output = []
with open("log.txt") as f:
for line in f:
values = []
line = line.split("element=(string)", 1)[1]
values.append(line.split(",", 1)[0])
line = line.split("time=(guint64)", 1)[1]
values.append(int(line.split(",", 1)[0]))
line = line.split("ts=(guint64)", 1)[1]
values.append(int(line.split(";", 1)[0]))
output.append(values)
Upvotes: 0