正则表达式分组和可选匹配

时间:2013-11-18 18:29:50

标签: java regex garbage-collection

首先:我对正则表达式不强。现在,那就在桌面上。 我正在构建一个使用组和可选组件的正则表达式。我遇到的问题是,我需要在两个不同的区域匹配一定数量,并给它们相同的组名。这似乎不起作用。

所以具体细节。我正在分析来自JVM的垃圾收集日志。 有问题的两行是完整的GC和常规的GC。

我打破了这些以使它们可读。

全线:

229980.058: [Full GC 229980.058: 
            [CMS: 2796543K->2796543K(2796544K), **13.3050667** secs]
            2983863K->2872464K(4067264K), 
            [CMS Perm : 325367K->325242K(1048576K)], 13.3054416 secs] 
            [Times: user=13.27 sys=0.03, real=13.31 secs] 

常规行:

2.752: [GC 2.752: 
       [ParNew: 1143680K->4938K(1270720K), **0.0243534** secs] 
       1143686K->4945K(4067264K), 0.0245283 secs] 
       [Times: user=0.05 sys=0.02, real=0.03 secs] 

如您所见,Full GC将CMS / tenured generation作为第一个字段区域。第二个没有这些,因为它只是常规集合。

为了捕获这些,正确的我已经使“CMS:”和“ParNew:”部分彼此可选。但是,我希望将每个时间作为一个组名称拉出来。 (我放的价值**)

我正在使用这个正则表达式:

\ d +。\ d +:[(Full \ s)?GC \ s \ d +。\ d +:[(CMS:\ s(?< JVM_TenuredGenHeapUsedBeforeGC> \ d +)+ K->(?< JVM_TenuredHeapUsedAfterGC> ; \ d +)K(\ d + K),\ S(小于?JVM_GCTimeTaken> \ d + \ d +)\ ssecs)。?     ?(ParNew:???\ S(\ d +)+ K->(小于JVM_NewGenHeapUsedAfterGC> \ d +)K((小于JVM_NewGenHeapSize> \ d +)K),\ S(小于JVM_GCTimeTaken> \ d + \ d +)\ ssecs)?] .. [为简洁而编辑]

简而言之..是否可以在不同的可选匹配上使用相同的组名?他们永远不会在同一条线上,所以我不知道为什么我不能这样做。

使用regexr进行测试似乎也失败了。谢谢!

3 个答案:

答案 0 :(得分:3)

  

我遇到的问题是,我需要在两个不同的区域匹配一定数量,并给它们相同的组名。

我会说这就是问题所在。我没有试过这个,但是我看到了引入命名组的更改列表,而这只是命名一个编号组。所以它无法运作。

给他们不同的名字并使用类似

的内容
Objects.firstNonNull(m.group("foo"), m.group("bar"))

如果您确定其中至少有一个非空(否则您将获得NPE)。或者写下你自己的无效接收单行。

答案 1 :(得分:3)

一些小实验表明Java不允许您在正则表达式中定义两次相同的捕获组名称。以下代码生成以下异常:

public class NamedCapturingGroupMain {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("(?<mygroup>a)|(?<mygroup>b)");
    }
}

例外:

Exception in thread "main" java.util.regex.PatternSyntaxException: Named capturing group <mygroup> is already defined near index 24

这里最简单的方法可能是定义两个不同的捕获组名称,如果第一个名称为null,则使用第二个名称。例如,如果您使用“JVM_GCTimeTakenFull”和“JVM_GCTimeTakenPartial”,然后执行以下操作:

String gcTimeTaken = matcher.group("JVM_GCTimeTakenFull");
if (gcTimeTaken == null) {
    gcTimeTaken = matcher.group("JVM_GCTimeTakenPartial");
}

答案 2 :(得分:2)

编辑 - 如果Java不允许重复名称,我错过了Java标记(我知道了 它不支持分支重置)你可以这样做,然后测试一个匹配 Full_GCCMS(可让您解释下一组)

无论哪种方式,您只需要一个JVM_GCTimeTaken组。

 # "\\d+\\.\\d+:\\s*\\[(?:(?<Full_GC>Full\\s*GC)|(?<GC>GC))\\s*(?<GC_Val>\\d+\\.\\d+):\\s*\\[(?:(?<CMS>CMS)|(?<ParNew>ParNew)):\\s*(?<HeapUsedBefore>\\d+)K->(?<HeapUsedAfter>\\d+)K\\((?<NewHeapSize>\\d+)K\\),\\s*(?<JVM_GCTimeTaken>\\d+\\.\\d+)\\s*secs\\]"


 \d+ \. \d+ : \s* 
 \[
     (?:
          (?<Full_GC> Full \s* GC )     # (1)
       |  (?<GC> GC )               # (2)
     )
     \s* 
     (?<GC_Val> \d+ \. \d+ )            # (3)
     : 
     \s* 
 \[
     (?:
          (?<CMS> CMS )                 # (4)
       |  (?<ParNew> ParNew )           # (5)
     )
     : \s* 
     (?<HeapUsedBefore> \d+ )           # (6)
     K->
     (?<HeapUsedAfter> \d+ )            # (7)
     K
     \(
     (?<NewHeapSize> \d+ )              # (8)
     K
     \)
     , \s* 
     (?<JVM_GCTimeTaken> \d+ \. \d+ )   # (9)
     \s* 
     secs
 \]