正则表达式捕获现有和不存在的数据

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_MINORERROR_ 和 1+ 个数字
  • ) 关闭组 2
  • (?:\w+:(\w+))? 可选择匹配 1+ 个单词字符和 :,然后在 组 3 中捕获 1+ 个单词字符

Regex demo

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