Образец Java Regex, сопоставляющий первое вхождение "границы" после любой последовательности символов

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

например:.

String text = "this should match from A to the first B and not 2nd B, got that?";
Pattern ptrn = Pattern.compile("\\b(A.*B)\\b");
Matcher mtchr = ptrn.matcher(text);
while(mtchr.find()) {
    String match = mtchr.group();
    System.out.println("Match = <" + match + ">");
}

печатает:

"Match = <A to the first B and not 2nd B>"

и я хочу, чтобы он печатался:

"Match = <A to the first B>"

Что мне нужно изменить внутри шаблона?

Ответ 1

Сделайте свой * неживым/неохотным, используя *?:

Pattern ptrn = Pattern.compile("\\b(A.*?B)\\b");

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

См. "Недостаточные квантификаторы" документы и этот учебник.

Ответ 2

Не используйте жадные выражения для сопоставления, т.е.:

Pattern ptrn = Pattern.compile("\\b(A.*?B)\\b");

Ответ 3

* - это жадный квантификатор, который соответствует как можно большему количеству символов, чтобы удовлетворить шаблон. До последнего события B в вашем примере. Вот почему вам нужно использовать неохотный: *?, который будет обрабатывать как можно больше символов. Итак, ваш шаблон должен быть слегка изменен:

Pattern ptrn = Pattern.compile("\\b(A.*?B)\\b");

Смотрите "неохотные квантификаторы" в документы и этот учебник.

Ответ 4

Возможно, более явным, чем отказ * неохотно/ленивый, будет сказать, что вы ищете A, за которым следует куча вещей, которые не являются B, а затем B:

Pattern ptrn = Pattern.compile("\\b(A[^B]*B)\\b");