【问题标题】:Regex using several repeatable capture groups使用多个可重复捕获组的正则表达式
【发布时间】:2010-07-07 03:58:42
【问题描述】:

我有一组来自 Radius 消息的非常统一的数据,我需要将这些数据添加到我们的日志管理解决方案中。该产品提供了使用正则表达式以几种形式提取各种数据的能力。

1) 您希望提取的每条数据的单独正则表达式

    <data 1 = regex statement>
    <data 2 = different regex statement>    
    <data 2 = yet another regex statement>

2) 使用捕获组的奇异正则表达式

    <group = regex statement with capture groups>
        <data 1 = capture group[X]
        <data 2 = capture group[Y]
        <data 3 = capture group[Z]
    </group>

<158>Jul 6 14:33:00 radius/10.10.100.12 radius: 07/06/2010 14:33:00 AP1A-BLAH (10.10.10.10) - 6191 / Wireless - IEEE 802.11: abc1234 - Access-Accept (AP: 000102030405 / SSID: bork / Client: 050403020100) 

我想提取几位数据,它们都在空格之间。类似于以下内容的内容似乎没有效率:

(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s

那么,鉴于上面的数据,最有效的 Java 正则表达式将抓取一组空格之间的每个字段并将其放入一个捕获组中?

【问题讨论】:

  • 为什么那个正则表达式似乎没有效率?你有性能问题吗?
  • 多次重复正则表达式的同一部分(在本例中为 29 次)似乎不是最佳选择。我没有做过很多这样统一的重复,所以我不确定它是否可以以任何方式缩短。
  • 29 组?您应该考虑使用split(),正如@Tim 的第二个答案所建议的那样。
  • @Alan:看起来 OP 正在使用一些基于正则表达式的特殊工具(即提到的整个 &lt;data...&gt;&lt;group...&gt; 语法)。否则split 甚至Scanner 是最好的。
  • @Alan, @poly - 就是这样。我有一个接口,可以通过正则表达式抓取部分日志以插入标准数据库(因此您可以跨多个不同的非标准日志文件关联 MAC、用户名等)。因此,虽然我知道有更好的方法来处理此类条目,但不幸的是,我无法使用这些方法。

标签: java regex


【解决方案1】:

你可以更具体:

(\S*)\s(\S*)\s(\S*)\s(\S*)\s(\S*)\s(\S*)\s

\S 匹配非空格字符 - 这通过避免回溯使正则表达式更有效,并且如果输入不符合模式,它允许正则表达式更快地失败。

即,当将您的正则表达式应用于字符串Jul 6 14:33:00 radius/10.10.100.12 radius: 07/06/2010 时,正则表达式引擎需要执行 2116 个步骤才能发现它不匹配。上面的正则表达式在 168 个步骤中失败。

Alan Moore 建议使用 (\S*+)\s(\S*+)\s(\S*+)\s(\S*+)\s(\S*+)\s(\S*+)\s 带来了另一项改进 - 现在正则表达式在 24 步内失败(比初始正则表达式快近一百倍)。

如果匹配成功,Alan 和我的解决方案是等价的,你的正则表达式会慢十倍左右。

【讨论】:

  • 您可以更进一步,使所有量词都具有所有格,即(\S*+)。没有比这更有效率的了。
【解决方案2】:

我只是想到了别的东西 - 为什么不简单地将字符串拆分为空格?

String[] splitArray = subjectString.split("\\s");

【讨论】:

  • 我不能这样做的唯一原因是我提供的界面是正则表达式,不包括做这样有趣的事情的能力。不过,第一个答案是完美的 - 正则表达式在每秒处理大量日志时应该足够高效。
猜你喜欢
  • 1970-01-01
  • 2017-09-13
  • 2011-03-11
  • 2017-01-07
  • 2019-12-19
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多