python-3.x - 匹配两个lookbehinds之一
问题描述
我正在尝试通过从日志文件中Pandas.DataFrame
提取设备来填充 a 中的列。id
问题是它id
前面可能有两个单独的模式,如下所示:
模式一:
(?<=cameraId=\')([a-z0-9-]+))
模式二:
(?<=/live/)([a-z0-9-]+)
注意:一条线不可能同时具有两种模式
问题是我使用该Pandas.String.str.findall()
方法,并且我希望填充两种模式。
我可以成功实现预期的结果,如下面的代码所示:
import pandas as pd
line_1 = 'INFO:2021-04-19 00:25:10,647:instance_manager.py:MainProcess:1:got event notificationName=\'DETECTION_STARTED\' cameraId=\'ab1c-ab6c-a6f6-a6d6-ab666\' timestamp=\'2021-04-19T00:24:08.192169Z\''
line_2 = 'INFO:2021-04-19 00:25:11,278:instance_manager.py:MainProcess:1:An old record record for the stream rtsp://127.0.1.1:6666/live/a001-a00a-0016-a006-ab606.stream was successfully updated in the DB!'
df = pd.DataFrame(columns=['type', 'ts', 'process', 'subprocess', 'line', 'message'])
line_1_parsed = pd.Series([line_1]).str.extract(r'(?P<type>[^:]+):(?P<ts>.+,\d+):(?P<process>[^:]+):(?P<subprocess>[^:]+):(?P<line>[^:]+):(?P<message>[^$]+)')
line_2_parsed = pd.Series([line_2]).str.extract(r'(?P<type>[^:]+):(?P<ts>.+,\d+):(?P<process>[^:]+):(?P<subprocess>[^:]+):(?P<line>[^:]+):(?P<message>[^$]+)')
df =df.append(line_1_parsed, ignore_index=True)
df =df.append(line_2_parsed, ignore_index=True)
df.loc[:, 'cam_id'] = df.loc[:, 'message'].str.findall('(?<=cameraId=\')([a-z0-9-]+)|(?<=/live/)([a-z0-9-]+)')
df
,但它们以元组(模式 1,模式 2)的形式返回,如下所示Current Output
:
电流输出:
type ts process subprocess line message cam_id
0 INFO 2021-04-19 00:25:10,647 instance_manager.py MainProcess 1 got event notificationName='DETECTION_STARTED'... [(ab1c-ab6c-a6f6-a6d6-ab666, )]
1 INFO 2021-04-19 00:25:11,278 instance_manager.py MainProcess 1 An old record record for the stream rtsp://127... [(, a001-a00a-0016-a006-ab606)]
我确实理解这是因为它尝试了两种模式并返回两者的匹配项,但我更希望它只包含成功的模式。
当然,我可以通过以下方式手动提取它:
df.loc[:, 'cam_id'] = df.loc[:, 'cam_id'].apply(lambda cam_id_tuple: cam_id_tuple[0][0] if cam_id_tuple[0][0] != '' else cam_id_tuple[0][1])
df
但它是一个相当麻烦的解决方案,而且不可扩展,以防我想添加模式。
期望的输出:
type ts process subprocess line message cam_id
0 INFO 2021-04-19 00:25:10,647 instance_manager.py MainProcess 1 got event notificationName='DETECTION_STARTED'... [ab1c-ab6c-a6f6-a6d6-ab666]
1 INFO 2021-04-19 00:25:11,278 instance_manager.py MainProcess 1 An old record record for the stream rtsp://127... [a001-a00a-0016-a006-ab606]`
Nonte:该cam_id
列包含字符串而不是元组
提前致谢。
解决方案
我们可以使用str.extract
具有单个捕获组的正则表达式模式
df['message'].str.extract(r'(?:cameraId=\'|/live/)([a-z0-9-]+)', expand=False)
0 ab1c-ab6c-a6f6-a6d6-ab666
1 a001-a00a-0016-a006-ab606
Name: message, dtype: object
正则表达式详细信息:
(?:cameraId=\'|/live/)
: 非捕获组cameraId=\'
: 第一个选择匹配字符的cameraId='
字面意思/live/
: 第二种选择匹配字符的/live/
字面意思
([a-z0-9-]+)
: 第一个捕获组[a-z0-9-]+
:匹配列表中存在的任何字符[a-z0-9-]
一次或多次
见网上regex demo
推荐阅读
- r - 将一行与前 3 行进行比较
- flutter - 如何在颤动中滚动列表视图时检查位置?
- python - 使用 pathlib glob 提取文件名以 0/ 1 开头的路径的模式
- android - 更改 Android 视图中的项目顺序
- javascript - 我的 Javascript 表单验证器不起作用(?
- assembly - PUTS 跳转到 PC 的开头?
- amazon-web-services - 为什么我的 AWS ECS 服务无法启动我的任务?
- python - 绩效评估模型不起作用
- bash - bash 中这个表达式的解释是什么:(($a<0?10:$a<100))?
- mysql - MySql中Where语句中如何使用时间差异