当某些请求或操作发生时,我有插入了可选请求数据的系统日志。
例如考虑以下日志条目
YYYY-MM-DDTHH:mm:ss PID | INFO | endpoint=SomeEndpoint, transactionId=12345, userId=67890 | Some log message
我要在这里用正则表达式解析的部分将是:
endpoint=SomeEndpoint, transactionId=12345, userId=67890
该附加数据可以按任何顺序排列,可能会丢失某些数据或将其完全丢失。 例如,所有这些都可以作为日志消息:
YYYY-MM-DDTHH:mm:ss PID | INFO | transactionId=12345, endpoint=SomeEndpoint, userId=67890 | Some log message
YYYY-MM-DDTHH:mm:ss PID | INFO | userId=67890, endpoint=SomeEndpoint | Some log message
YYYY-MM-DDTHH:mm:ss PID | INFO | transactionId=12345 | Some log message
YYYY-MM-DDTHH:mm:ss PID | INFO | | Some log message
我设法像这样使用正向提前匹配来随机匹配它们:
\|\s*(?=[^\|]*endpoint=(?<endpoint>\w+))(?=[^\|]*transactionId=(?<transactionId>[\w-]+))(?=[^\|]*userId=(?<userId>[\w-]+)).*\s*\|
但这需要我让所有人都在那里进行比赛。有没有办法只匹配内部可用数据?如果某些缺少或全部丢失,我希望正则表达式通过。如果有数据,我希望在特定的正则表达式组中使用。
答案 0 :(得分:2)
如果在条件范围内使用 regex有条件的正则表达式,则可以在将文本匹配到组中之前检查外观是否成功。
我更改了您的正则表达式以满足您的要求。
[^|]+\|[^|]+\|\s*(?(?=[^\|]*endpoint=)(?=[^\|]*endpoint=(?<endpoint>\w+)))(?(?=[^\|]*transactionId=)(?=[^\|]*transactionId=(?<transactionId>[\w-]+)))(?(?=[^\|]*userId=)(?=[^\|]*userId=(?<userId>[\w-]+))).*\s*\|
答案 1 :(得分:2)
另一个选择可能是使用\G
,它将在上一个匹配项的末尾或字符串的开头进行匹配。
然后使用您可以参考的命名捕获组来检查其中存在哪些值。
(?:\G(?!^)|[^|]+\|[^|]+\|)\s*(?:transactionId=(?<transactionId>[\w-]+)|endpoint=(?<endpoint>\w+)|userId=(?<userId>[\w-]+)),?
说明
(?:
非捕获组
\G(?!^)
断言上一场比赛的结束,如果不是开始的话|
或[^|]+\|[^|]+\|)\s*
从开始比赛开始2次,而不是|
,然后是|
(?:
非capturiing组
transactionId=(?<transactionId>[\w-]+)
匹配命名捕获组中的transactionId |
或endpoint=(?<endpoint>\w+)
匹配命名捕获组中的端点|
或userId=(?<userId>[\w-]+
匹配命名捕获组中的userId )
关闭群组),?
关闭组并匹配可选的逗号