3

我想使用 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/empty t 存在。它需要为每一行返回一些东西。这将被插入到 LogParser 中,以便我们可以查询或记录特定订单或其他变量)

4

3 回答 3

4

如果您将<order>组设为可选,则该<before>组将始终匹配整行,因此即使存在 OrderId,匹配也会成功,但不会捕获 OrderId。在这种情况下,让它变得懒惰无济于事 ( (?<before>.*?)) (因为该<after>组匹配所有内容)。

但是,如果我理解正确的话,你可以在一个正则表达式中做所有你想做的事情。例如,假设您想要每行后面的单词Status set to(如果存在)后面的数字OrderId:(如果存在),那么您可以使用正则表达式

^
(?(?=.*Status\sset\sto\s)(?=.*Status\sset\sto\s(?<status>\w+))|)
(?(?=.*OrderId:)(?=.*OrderId:(?<order>\d+))|)

在每一行上并检查组<status>和/或<order>是否匹配。根据需要展开。

这假设您的正则表达式引擎支持条件,这是 .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.

我们需要两个紧跟前行的原因:我们不希望正则表达式引擎实际消耗当前行中的任何字符,因为我们不知道条目的顺序,所以每次搜索都需要从行的开头。(另一方面,如果条目的顺序始终是固定的,那么正则表达式可以简化一点)。

于 2012-07-20T16:03:03.243 回答
0

使用字符串扫描方法

如果您只需要 OrderId 记录编号,则可以通过扫描字符串以查找匹配表达式来简化此任务。例如,假设您的日志数据存储在 String log中,在 Ruby 中您可以执行以下操作:

log.scan /OrderId:(\d+)/
=> [["102602"], ["102603"]]

只有匹配的文本将被存储。没有匹配的行将不存储数组值。

于 2012-07-20T16:18:09.327 回答
0


您可以使用理解列表返回一个 id 列表:

 >>> import re
 >>> [ re.sub( r".*OrderId:(\d*).*", r"\1", line ) for line in logs.readlines() if 'OrderId' in line ]
 ['102602', '102603']
于 2012-07-20T16:46:13.500 回答