我想使用RE来解析日志文件并返回orderid(如果存在)。例如:
以下是示例日志
2012-07-19 12:05:04,288 [22] INFO AddQueueCommand [(null)] - Status set to Subscribed
2012-07-19 12:05:04,288 [23] INFO FooBarProviderFactory [(null)] - Missing Function : OrderId:102602 : Method:AddOrderToId : application:11
2012-07-19 12:05:04,288 [22] INFO AddQueueCommand [(null)] - Status set to Pending
2012-07-19 12:05:04,288 [23] INFO AddSubscription [(null)] - Subscription Added. OrderId:102603 : application:15
2012-07-19 12:05:04,288 [22] INFO AddQueueCommand [(null)] - Status set to Subscribed
我想要做的是使用正则表达式,以便我可以解析日志消息的组件。但是当存在“OrderId”时,我希望能够解析orderid#。
这是我到目前为止所做的:
^
(?<before>.*)
(?<order>((?<=OrderId\:\s*)\d*))
(?<after>.*)
$
非常适合解析包含它们的行的orderid,但是当行没有它们时它会失败。我试过添加“?”零或一个到订单行然后解析所有行,但从不解析实际的orderid。它们总是空的。
希望有人能看出我做错了什么。谢谢!
(我希望它解析每一行,因为我要从每一行解析多个id值,它们可能存在也可能不存在。我希望它返回值,如果我搜索的是存在或null /空如果它不存在。它需要为每一行返回一些内容。这将插入到LogParser中,以便我们可以查询或记录特定的订单或其他变量)
答案 0 :(得分:3)
如果您将<order>
组设为可选,则<before>
组将始终与整行匹配,因此匹配成功而不捕获OrderId,即使它在那里。在这种情况下,使其变得懒惰((?<before>.*?)
)会有所帮助(因为<after>
组会匹配所有内容)。
但如果我理解正确的话,你可以在一个正则表达式中做你想做的所有事情。例如,假设您想要Status set to
之后的单词(如果存在)和每行OrderId:
之后的数字(如果存在),那么您可以使用正则表达式
^
(?(?=.*Status\sset\sto\s)(?=.*Status\sset\sto\s(?<status>\w+))|)
(?(?=.*OrderId:)(?=.*OrderId:(?<order>\d+))|)
每行并检查论坛<status>
和/或<order>
是否匹配。必要时展开。
这假设你的正则表达式引擎支持conditionals,这是.NET,Perl和PCRE的情况。
<强>解释强>
(? # Conditional: IF it's possible to match...
(?=.*OrderId:) # any string, followed by "OrderId:"
# THEN try to match this:
(?= # Lookahead assertion:
.*OrderId: # any string, followed by "OrderId:"
(?<order>\d+) # followed by a number --> capture in group <status>
) # End of lookahead
| # ELSE try to match this:
# the empty string (always succeeds)
) # End of conditional.
我们之所以需要两个前瞻:我们不希望正则表达式引擎实际消耗当前行中的任何字符,因为我们不知道条目将在哪个顺序,因此每个搜索都需要从行的开头开始。 (另一方面,如果条目的顺序总是固定的,那么正则表达式可以简化一点)。
答案 1 :(得分:0)
如果您只想要OrderId记录编号,则可以通过扫描字符串以查找匹配的表达式来简化此任务。例如,假设您的日志数据存储在String log 中,在Ruby中您可以执行以下操作:
log.scan /OrderId:(\d+)/
=> [["102602"], ["102603"]]
仅存储匹配的文本。没有匹配的行不会存储数组值。
答案 2 :(得分:0)
您可以返回包含理解列表的ID列表:
>>> import re
>>> [ re.sub( r".*OrderId:(\d*).*", r"\1", line ) for line in logs.readlines() if 'OrderId' in line ]
['102602', '102603']