技术编程|30 分钟轻松搞定正则表达式基础( 五 )


知道了各个字段的正则后 , 我们可以将它们各自写成一个分组 , 分组之间填充上其余元字符 , 把匹配整行日志的正则表达式写出来 , 如下:
(\d{4}-\d{2}-\d{2}\s*\d{2}:\d{2}:\d{2})\s*\[(INFO)\]\s*.*:((\d{1,3}\.){3}\d{1,3}).*:(\w+@\w+\.\w+)\D*(\d+)\D*(\d+)KB
现在我们通过这个正则表达式可以抓取出日志文件中这种格式的日志字符串 , 再根据组号就可以拿出来对应的数据了 。不过根据组号取数据可能会有些含糊不清 , 或许我们可以给每个分组进行命名(使用python支持的方式) , 形成如下正则表达式:
(?P\d{4}-\d{2}-\d{2}\s*\d{2}:\d{2}:\d{2})\s*\[(?P INFO)\]\s*.*:(?P (\d{1,3}\.){3}\d{1,3}).*:(?P \w+@\w+\.\w+)\D*(?P \d+)\D*(?P \d+)KB
好了现在我们可以很清楚的看到 , 表示时间的分组命名为Time , 依次类推 。接下来 , 我们可以使用上述正则表达式去抓取一行日志 , 再通过分组的名称拿到对于的字符串数据了 。具体的代码可以参考下面的样例:
import redef reg_deal(pattern_list, text, func_dict=None): if func_dict is None: func_dict = {} for pattern in pattern_list: match_obj = re.match(pattern, text) if match_obj: return {k: func_dict.get(k, lambda x: x)(v) for k, v in match_obj.groupdict().items()}if __name__ == '__main__': email_pattern = r"(?P\d{4}-\d{2}-\d{2}\s*\d{2}:\d{2}:\d{2})\s*\[(?P INFO)\]\s*.*:(?P (\d{1," \ r"3}\.){3}\d{1,3}).*:(?P \w+@\w+\.\w+)\D*(?P \d+)\D*(?P \d+)KB" phone_pattern = r"(?P \d{4}-\d{2}-\d{2}\s*\d{2}:\d{2}:\d{2})\s*\[(?P INFO)\]\s*.*:(?P (\d{1," \ r"3}\.){3}\d{1,3}).*:(?P ((\+|00)86)?1[3-9]\d{9})\D*(?P \d+)\D*(?P \d+)KB" warn_pattern = r"(?P \d{4}-\d{2}-\d{2}\s*\d{2}:\d{2}:\d{2})\s*\[(?P WARN)\]\s*.*:(?P (\d{1," \ r"3}\.){3}\d{1,3}).*" error_pattern = r"(?P \d{4}-\d{2}-\d{2}\s*\d{2}:\d{2}:\d{2})\s*\[(?P ERROR)\]\s*(?P .*)" pattern_list = [email_pattern, phone_pattern, warn_pattern, error_pattern] status_dict={ '1': 'Sucess', '2': 'Fail' } func_dict = { 'status': lambda x: status_dict[x], 'data_size': lambda x: int(x)/1024 } result_list = [] with open('logcontent.log', 'r', encoding='utf-8') as f: for data in f: result_dict = reg_deal(pattern_list, data, func_dict) result_list.append(result_dict) print(result_list)
代码中实现了一个函数reg_deal , 后面代码都是对于这个函数的实际应用 , 该函数入参为:正则表达式组成的列表、待匹配的字符串、特殊函数组成的字典 。其先循环将字符串与列表中各个正则表达式进行匹配 , 匹配成功后得到一个匹配对象 , 调用该匹配对象的groupdict函数可以返回一个结果字典 , 该结果字典的键为分组的名称 , 值为分组匹配到的值 。针对这一结果字典再进行一步特殊函数处理 , 如上述中的status字段日志中是码值 , 但输出结果需要是具体的汉字 。故对其进行了一步码值转换操作 , 对与数据大小将KB转化成了MB 。
若使用该函数 , 需自己将正则表达式写出来并对正则表达式中的分组进行命名 , 若有些分组数据需要特殊处理 , 则维护一个特殊函数字典 , 键为分组名 , 值为函数(匿名函数或者是函数名称) 。将参数传入后即可获得结果字典或者 None 。得到结果字典后具体怎么处理就看你接下来的发挥啦 。


推荐阅读