正则表达式捕获现有和不存在的数据
Regex Expression Capture Existing and Non Existing Data
我正在尝试对一些日志进行分类,以便在 Python Pandas 中进一步分析它们。日志示例如下所示:
Event: Task_01Error:NO_ERROR
Event: Task_01Error:ERROR_MINOR
Event: Task_02Error:NO_ERROR
Event: Task_03Error:ERROR_01Details:BadData
Event: Task_03Error:ERROR_MINOR
我需要将它们分类为(我想要的输出):
Task, ErrorType,Details
01,NO_ERROR,NA
01,ERROR_MINOR,NA
02,NO_ERROR,NA
03,ERROR_01,BadData
03,ERROR_MINOR,NA
到目前为止我得到的是:
^Event: Task_(.*)Error:(.*)Details:(.*$)
仅匹配第四个条目(如预期)。但我实际上需要它来匹配“详细信息:”字符串之后的信息,或者如果字符串不存在则什么都不匹配。我需要这种方式的原因是我可以将正则表达式与 Pandas Series String Extract.
一起使用
换句话说,在最后一组我需要匹配:
Details:(.*$) OR ()
我知道肯定有一个简单的方法可以做到这一点,但我就是想不出来。
谢谢!
使用赋值函数创建 2 个新列:
df.assign(
ErrorType = lambda x: x['event'].apply(lambda s: s.split(':')[2].split('Details')[0]),
Details = lambda x: x['event'].apply(lambda s: s.split('Details:')[1] if len(s.split('Details:'))>1 else 'NA')
)
您不需要正则表达式,因为使用拆分很容易提取数据
您也可以在阅读时解析日志文件。
import re
path_to_file = "/mnt/ramdisk/in.log"
# capture event and err-detail
patt = re.compile(r"""
Event:\sTask_(\d+)
Error:(.+)
""", re.VERBOSE)
ls = [] # output container
with open(path_to_file) as f:
for line in f:
# 1. split task and err-detail
match_obj = patt.match(line)
ev = match_obj.group(1)
# 2. split error and detail
err_detail = match_obj.group(2).split("Details:")
if len(err_detail) == 1:
ls.append([ev, err_detail[0], None]) # or "NA"
else:
ls.append([ev, err_detail[0], err_detail[1]])
df = pd.DataFrame(ls, columns=["Task", "ErrorType", "Details"])
结果:
print(df)
Task ErrorType Details
0 01 NO_ERROR None
1 01 ERROR_MINOR None
2 02 NO_ERROR None
3 03 ERROR_01 BadData
4 03 ERROR_MINOR None
对于一个模式,您可以使用 3 个捕获组,其中第三组是可选部分。
如果第3组不存在,可以N/A
^Event:\s+Task_(\d+)Error:(NO_ERROR|ERROR_(?:MINOR|\d+))(?:\w+:(\w+))?
说明
^
字符串开头
Event:\s+Task_
匹配 Event:\s+Task_
(\d+)
捕获 组 1,匹配 1+ 个数字
Error:
字面匹配
(
捕获 第 2 组
=- NO_ERROR
按字面匹配
|
或
ERROR_(?:MINOR|\d+)
匹配 ERROR_MINOR
或 ERROR_
和 1+ 个数字
)
关闭组 2
(?:\w+:(\w+))?
可选择匹配 1+ 个单词字符和 :,然后在 组 3 中捕获 1+ 个单词字符
import re
import pandas as pd
regex = r"^Event:\s+Task_(\d+)Error:(NO_ERROR|ERROR_(?:MINOR|\d+))(?:\w+:(\w+))?"
test_str = ("Event: Task_01Error:NO_ERROR\n"
"Event: Task_01Error:ERROR_MINOR\n"
"Event: Task_02Error:NO_ERROR\n"
"Event: Task_03Error:ERROR_01Details:BadData\n"
"Event: Task_03Error:ERROR_MINOR")
matches = re.findall(regex, test_str, re.MULTILINE)
df = pd.DataFrame(matches, columns=["Task", "ErrorType", "Details"])
print(df)
输出
Task ErrorType Details
0 01 NO_ERROR
1 01 ERROR_MINOR
2 02 NO_ERROR
3 03 ERROR_01 BadData
4 03 ERROR_MINOR
我正在尝试对一些日志进行分类,以便在 Python Pandas 中进一步分析它们。日志示例如下所示:
Event: Task_01Error:NO_ERROR
Event: Task_01Error:ERROR_MINOR
Event: Task_02Error:NO_ERROR
Event: Task_03Error:ERROR_01Details:BadData
Event: Task_03Error:ERROR_MINOR
我需要将它们分类为(我想要的输出):
Task, ErrorType,Details
01,NO_ERROR,NA
01,ERROR_MINOR,NA
02,NO_ERROR,NA
03,ERROR_01,BadData
03,ERROR_MINOR,NA
到目前为止我得到的是:
^Event: Task_(.*)Error:(.*)Details:(.*$)
仅匹配第四个条目(如预期)。但我实际上需要它来匹配“详细信息:”字符串之后的信息,或者如果字符串不存在则什么都不匹配。我需要这种方式的原因是我可以将正则表达式与 Pandas Series String Extract.
一起使用换句话说,在最后一组我需要匹配:
Details:(.*$) OR ()
我知道肯定有一个简单的方法可以做到这一点,但我就是想不出来。
谢谢!
使用赋值函数创建 2 个新列:
df.assign(
ErrorType = lambda x: x['event'].apply(lambda s: s.split(':')[2].split('Details')[0]),
Details = lambda x: x['event'].apply(lambda s: s.split('Details:')[1] if len(s.split('Details:'))>1 else 'NA')
)
您不需要正则表达式,因为使用拆分很容易提取数据
您也可以在阅读时解析日志文件。
import re
path_to_file = "/mnt/ramdisk/in.log"
# capture event and err-detail
patt = re.compile(r"""
Event:\sTask_(\d+)
Error:(.+)
""", re.VERBOSE)
ls = [] # output container
with open(path_to_file) as f:
for line in f:
# 1. split task and err-detail
match_obj = patt.match(line)
ev = match_obj.group(1)
# 2. split error and detail
err_detail = match_obj.group(2).split("Details:")
if len(err_detail) == 1:
ls.append([ev, err_detail[0], None]) # or "NA"
else:
ls.append([ev, err_detail[0], err_detail[1]])
df = pd.DataFrame(ls, columns=["Task", "ErrorType", "Details"])
结果:
print(df)
Task ErrorType Details
0 01 NO_ERROR None
1 01 ERROR_MINOR None
2 02 NO_ERROR None
3 03 ERROR_01 BadData
4 03 ERROR_MINOR None
对于一个模式,您可以使用 3 个捕获组,其中第三组是可选部分。
如果第3组不存在,可以N/A
^Event:\s+Task_(\d+)Error:(NO_ERROR|ERROR_(?:MINOR|\d+))(?:\w+:(\w+))?
说明
^
字符串开头Event:\s+Task_
匹配Event:\s+Task_
(\d+)
捕获 组 1,匹配 1+ 个数字Error:
字面匹配(
捕获 第 2 组 =-NO_ERROR
按字面匹配|
或ERROR_(?:MINOR|\d+)
匹配ERROR_MINOR
或ERROR_
和 1+ 个数字
)
关闭组 2(?:\w+:(\w+))?
可选择匹配 1+ 个单词字符和 :,然后在 组 3 中捕获 1+ 个单词字符
import re
import pandas as pd
regex = r"^Event:\s+Task_(\d+)Error:(NO_ERROR|ERROR_(?:MINOR|\d+))(?:\w+:(\w+))?"
test_str = ("Event: Task_01Error:NO_ERROR\n"
"Event: Task_01Error:ERROR_MINOR\n"
"Event: Task_02Error:NO_ERROR\n"
"Event: Task_03Error:ERROR_01Details:BadData\n"
"Event: Task_03Error:ERROR_MINOR")
matches = re.findall(regex, test_str, re.MULTILINE)
df = pd.DataFrame(matches, columns=["Task", "ErrorType", "Details"])
print(df)
输出
Task ErrorType Details
0 01 NO_ERROR
1 01 ERROR_MINOR
2 02 NO_ERROR
3 03 ERROR_01 BadData
4 03 ERROR_MINOR