2013-11-18 2 views
3

Во-первых: я не силен с регулярным выражением. Теперь это на столе. Я работаю над созданием регулярного выражения, которое использует группы, и дополнительные компоненты. Проблема, которую я имею, заключается в том, что мне нужно сопоставить определенное число в двух разных областях и дать им одно и то же имя группы. Это не работает.Группирование регулярных выражений и необязательные совпадения

Так что конкретные детали. Я анализирую журнал сбора мусора из 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/штатное поколение в качестве первой области поля. У второго нет таких, поскольку это всего лишь обычная коллекция.

Для того, чтобы их можно было захватить, исправьте, я сделал оба раздела «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)?] .. [отредактировано для краткости]

Короче .. Можно ли использовать одно и то же имя группы для разных необязательных совпадений? Они никогда не будут на одной линии, поэтому я не знаю, почему я не могу это сделать.

Тестирование этого с помощью регулярного выражения также, похоже, терпит неудачу. Благодаря!

ответ

3

Проблема, которую я имею, заключается в том, что мне нужно сопоставить определенное число в двух разных областях и дать им одно и то же имя группы.

Я бы сказал, что это проблема. Я не пробовал это, но я видел список изменений, в котором представлены именованные группы, и это просто название пронумерованной группы. Так что это не сработает.

Дайте им разные имена и использовать что-то вроде

Objects.firstNonNull(m.group("foo"), m.group("bar")) 

, если вы уверены, что по крайней мере один из них не равен нулю (в противном случае вы получите NPE). Или напишите свой собственный нуль-приемный однострочный.

2

Редактировать - Я пропустил тег Java, если Java не позволяет повторяющихся имен (и я знаю
он не поддерживает сброс ветви), вы можете сделать это, то тест на матч на
Full_GC AND CMS (что позволяет интерпретировать следующие группы)

В любом случае вам понадобится только одна группа 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 
\] 
+0

Упс, я бы подумал, что это Dot-Net. Извини за это. – sln

+0

Отлично! это действительно полезно. Благодаря! – jgauthier

+0

Редактированное сообщение для решения Java. – sln

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 

проще всего сделать, здесь, вероятно, будет определять два разных имени отлов группы, и использовать второй, если первый один нулевой. Например, если вы использовали «JVM_GCTimeTakenFull» и «JVM_GCTimeTakenPartial», а затем сделать что-то вроде:

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

Мне слишком лениво смотреть, но поддерживает ли Java 7 дубликаты имен? – sln

+1

@sln Когда вы пытаетесь «Pattern.compile», это очень простое регулярное выражение, указанное в моем ответе, вы получаете исключение PatternSyntaxException «Именованная группа захвата уже определена». Поэтому я думаю, что нет, Java 7 не поддерживает повторяющиеся имена, даже если они находятся во взаимоисключающих ветвях регулярного выражения. –

+1

Sheez, как раз когда Java собирается делать рекурсию. Ради Бога, я имею в виду, они просто должны были получить голову от своего a__ ~ – sln

Смежные вопросы