2014-11-06 6 views
3

В последнее время я играю с регулярным выражением на Java, и я нахожусь в проблеме, которую (теоретически) легко решить, но я блуждал, если есть более простой способ сделать это (Да, да я ленивый), проблема захвата группы несколько раз, это:Группа захвата несколько раз

public static void main(String[] args) { 
    Pattern p = Pattern.compile("A (IvI(.*?)IvI)*? A"); 
    Matcher m = p.matcher("A IvI asd IvI IvI qwe IvI A"); //ANY NUMBER of IvI x IvI 
    //Matcher m = p.matcher("A A"); 
    int loi = 0; //last Occurrence Index 
    String storage; 
    while (loi >= 0 && m.find(loi)) { 
     System.out.println(m.group(1)); 
     if ((storage = m.group(2)) != null) { 
      System.out.println(storage); 
     } 
     //System.out.println(m.group(1)); 
     loi = m.end(1); 
    } 
    m.find(); 
    System.out.println("2 opt"); 
    Pattern p2 = Pattern.compile("IvI(.*?)IvI"); 
    Matcher m2 = p2.matcher(m.group(1)); //m.group(1) = "IvI asd IvI IvI qwe IvI" 
    loi = 0; 
    while (loi >= 0 && m2.find(loi)) { 
     if ((storage = m2.group(1)) != null) { 
      System.out.println(storage); 
     } 
     loi = m2.end(0); 
    } 
} 

Использование ТОЛЬКОPattern pесть ли способ, чтобы получить то, что находится внутри IvI's? (в тестовой строке будут «asd» и «qwe»), учитывая, что может быть любое количество разделов IvI's, что-то похожее на то, что я пытаюсь сделать в первую очередь, а именно нахождение первого вхождения группы , затем переместив указатель и поиск следующей группы и так далее и так далее ...

Используя код, который я написал, что в то время как она возвращает asd IvI IvI qwe как 2-й группы, а не только asd, а затем qwe, в части I предположим, что это может быть из-за части (. *?), не предполагается, что она жадна, но все же она поднимается до qwe, потребляя две из IvI's. Я упоминаю об этом, потому что в противном случае я могу использовать конечный индекс те, у которых есть метод matcher.find(anInt), но он не работает; Я не думаю, что это что-то не так с регулярным выражением, так как следующий код работает без потребления IvI.

public static void main(String[] args) { 
    Pattern p = Pattern.compile("(.*?)IvI"); 
    Matcher m = p.matcher("bla bla blaIvI"); 
    m.find(); 
    System.out.println(m.group(1)); 
} 

Это печатает: bla bla bla

Существует решение я знаю (но я ленив помню)

(Также на первом коде, ржали «2 неавтоматического» сообщение) Решение разделяя его на подгруппы и используя другое регулярное выражение, где вы обрабатываете только эти подгруппы по одному за раз ...

BTW: Я сделал домашнее задание В this на странице упоминается

Поскольку группа захвата с квантификатором держится на своем номере, какое значение возвращает двигатель при проверке группы? Все двигатели возвращают последнее зафиксированное значение. Например, если вы сопоставляете строку A_B_C_D_ с ([A-Z] ) +, то при проверке соответствия группа 1 будет равна D. За исключением движка .NET все промежуточные значения теряются. По сути, группа 1 перезаписывается каждый раз, когда ее шаблон сопоставляется.

Но я все еще надеюсь, что ты дать мне хорошие новости ...

+1

Каков ваш ожидаемый результат в этом случае: «A IvI IvI IvI IvI IvI A» и этот случай «A IvI IvI IvI b IvI A IvI a IvI IvI b IvI A'? Обратите внимание, что двухступенчатое совпадение с 2-го шага regex 'IvI (. *?) IvI' не работает для первого случая. Во втором случае это один из тестовых случаев, которые я использовал при создании регулярного выражения с помощью этого метода: http://stackoverflow.com/questions/15268504/collapse-and-capture-a-repeating-pattern-in-a- single-regex-expression/15418942 # 15418942 – nhahtdh

+0

Для первого случая я мог бы получить a, затем «" [пробел], а затем я не смог бы найти другую пару IvI, строка не совпадение с шаблоном после b, для второго я бы получил a, затем b, а так как второй A соответствует шаблону, он остановится там – Ordiel

+0

Я не спрашиваю о вашем коде. Я спрашиваю о желаемом результате, если такие случаи случаются. – nhahtdh

ответ

5

Нет, к сожалению, как ваша цитата уже упоминает, то java.util.regex регулярное выражение реализация не поддерживает загрузку всех предыдущих значений повторяющейся группы захвата после одного матча. Единственный способ получить их, как показывает ваш код, - найти() несколько совпадений повторяющейся части вашего регулярного выражения.

Я также смотрел на других реализациях регулярных выражений в Java, например:

, но я не мог найти, что поддерживает его (только Microsoft .NET двигатель).Если я правильно понял, реализация регулярных выражений на основе государственных машин не может легко реализовать эту функцию. Однако java.util.regex не использует государственные машины.

Если кто-либо знает библиотеку регулярных выражений Java, которая поддерживает это поведение, поделитесь ею, потому что это будет мощная функция.

p.s. мне потребовалось некоторое время, чтобы понять ваш вопрос. Название хорошее, но тело путало меня о том, правильно ли я вас понял.

+0

Спасибо, и извините, я постараюсь, чтобы это было просто;) – Ordiel