2015-05-20 2 views
1

Я пытался ответить на вопрос недавно и, пытаясь его решить, столкнулся с вопросом.Как фиксировать все вложенные совпадения?

Учитывая следующий код

private void regexample(){ 
    String x = "a3ab4b5"; 

    Pattern p = Pattern.compile("(\\D+(\\d+)\\D+){2}"); 
    Matcher m = p.matcher(x); 
    while(m.find()){ 
     for(int i=0;i<=m.groupCount();i++){ 
      System.out.println("Group " + i + " = " + m.group(i)); 
     } 
    } 
} 

И выход

Group 0 = a3ab4b 
Group 1 = b4b 
Group 2 = 4

Есть ли прямой способ я пропускаю, чтобы получить значение 3? Шаблон должен искать два входа (\\D+(\\d+)\\D+) back-to-back, а a3a является частью матча. Я понимаю, что могу изменить выражение на (\\D+(\\d+)\\D+), а затем искать все совпадения, но это технически не то же самое. Это единственный способ сделать двойной поиск? т. е. Использовать заданный шаблон для соответствия строке, а затем снова искать для каждого подсчета внешней группы?

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

+2

Когда вы повторяете группу захвата, первый захват перезаписывается последним. –

ответ

3

Невозможно захватить несколько вхождений одной и той же группы (со стандартными двигателями регулярных выражений). Вы могли бы использовать что-то вроде этого:

Pattern.compile("(\\D+(\\d+)\\D+)(\\D+(\\d+)\\D+)"); 

Теперь, есть четыре группы, а не два, так что вы получите значение, которые вы ожидали.

This question имеет аналогичную проблему.

+0

Другими словами, «реструктурируйте ваше регулярное выражение, чтобы вы могли получить значение». :) Справедливо. – MadConan

+0

@MadConan: Обратите внимание, что '\\ D +) (\\ D +" неявно требует не менее двух цифр без двух цифр, а если есть более двух цифр, первая часть будет принимать n - 1 символ, тогда как вторая часть примет 1 символ из последовательности цифр без двух цифр. – nhahtdh