我有一个庞大的日志文件。我如何只使用json字符串,只有当下一行中有错误但在前一行中的'_____GP D __之后?
2017-04-22T11:27:11+06:00 smth.com pgp: [16136]: INFO:modules.gp.helpers.parameter_getter:_____GP D_____
2017-04-22T11:27:11+06:00 smth.com pgp: [16136]: {'D': 't12', 'telephone': None, 'from_time': '2016-04-22 11:30', 'C': 'C12', 'to_time': '2016-04-22 11:40', 'email': None}
2017-04-22T11:27:11+06:00 smth.com pgp: [16136]: INFO:tornado.access:200 POST /gp/C (192.168.1.240) 15.77ms
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: INFO:modules.security.authentication:LOADING USER...
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: INFO:modules.gp.helpers.parameter_getter:_____GP D_____
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: {'D': 'testim12', 'telephone': None, 'from_time': '2017-04-20 17:30', 'C': 'CnGP13', 'to_time': '2017-04-22 21:40', 'email': None}
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: ERROR:modules.common.actionexception:ActionError: [{'from': 'time is already passed'}]
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: Traceback (most recent call last):
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: File "/app/src/modules/base/actions/base_action.py", line 96, in do_action
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: self._produce_response()
2017-04-22T11:28:19+06:00 smth.com pgp: [16136]: modules.common.actionexception.ActionValidationErr: []
例如来自我希望的这个日志文件
'{'D':'testim12','电话':无,'from_time':'2017-04-20 17:30','C':'CnGP13','to_time':'2017-04 -22 21:40','email':无}'。
只有当我有一个例外时,在下一行中出现'ERROR:modules.common.actionexception:ActionError:'?我该怎么做?
答案 0 :(得分:0)
你可以使用这个,其中JSON字符串在捕获组1中
(?m)^.*?_____GP[ ]D_____.*\r?\n\s*^[^{\r\n]+(.+)\r?\n\s*^.*?ERROR:.*
https://regex101.com/r/UQ8gni/2
解释
(?m) # Modifiers: multi-line
^ .*? _____GP [ ] D_____ .* # Line that starts error block
\r? \n \s* # Required newline
^ [^{\r\n]+ # Up to start of Json string
( .+ ) # (1), Json string
\r? \n \s* # Required newline
^ .*? ERROR: .* # Line that ends error block
答案 1 :(得分:0)
这与one you had yesterday的问题相同,只是在选择行之前进行额外检查 - 例如检查下一行是否包含]: ERROR:
字符串:
found_line = None # store for our matched line
with open("input.log", "r") as f: # open your log file
for line in f: # read it line by line
if line.rstrip()[-14:] == "_____GP D_____": # if a line ends with our string...
found_line = next(f).rstrip() # grab the next line as our potential candidate
if next(f).find("]: ERROR:") != -1: # if the next line contains an error marker
break # match found, break out as we don't need to search any more...
else: # the next line wasn't an error...
found_line = None # ... reset the potential result and continue searching
但是,由于您的found_line
实际上会包含整行(包括时间戳),因此您需要先将其删除,这一切都取决于记录器的设置方式。根据您的数据,合理的方法是跳过第一个39
字符(<date-time> smth.com pgp:
)并在下一个冒号后拾取所有内容,假设以下括号中的数字可以更改(如果不是 - 您可以删除第一个n
字符并完成它:)
if found_line:
found_line = found_line[found_line.find(":", 39) + 1:].strip()
小心,那个&#39;错误&#39;如果某些记录的数据包含该确切模式,则检查可能会失败 - 如果您想要使用它,您可以尝试使用我们用于将JSON从日志行中取出的类似技术并检查它是否以{{1开头}}
你也应该尝试自己做事而不是盲目地从SO中复制代码 - 你不会以这种方式学到很多东西。
答案 2 :(得分:0)
使用生成器功能:
def getjson (f):
for line in filter(lambda x: '_GP D_' in x, f):
line1 = next(f)
line2 = next(f).split(' ', 4)
if line2[4].startswith('ERROR'):
yield line1.rstrip().split(' ', 4)[4]
with open('input.log', 'r') as f:
for json in getjson(f):
print(json)
生成器的一个兴趣是它将捕获由next()
引起的最终stopIteration异常(例如,当_G PD_
行之后少于2行时。) 并停止。
请注意,此方法假定_G PD_
行至少分隔两行。