Вкл. ?
для необязательного или нежелательного
Метасимвол ?
в Java regex (и некоторых других разновидностях) может иметь два совершенно разных значения, в зависимости от того, где он появляется.Сразу после спецификатора повторения ?
является неохотным квантификатором, а не «ноль или один» / «необязательный» спецификатор повторения.
Таким образом, #{5}?
не означает «необязательно совпадение 5 #
».Это на самом деле говорит "матч 5 #
неохотно".Возможно, не имеет смысла пытаться сопоставить «ровно 5, но как можно меньше», но на самом деле это означает, что этот шаблон означает.
Группировка на помощь!
Один из способов решения этой проблемы - сгруппировать необязательный шаблон как (…)?
.Примерно так должно работать для этой проблемы:
(#{5})?<\w+>
Теперь ?
не сразу следует за спецификатором повторения (то есть *
, +
, ?
или {…}
);он следует за закрывающей скобкой, используемой для группировки.
В качестве альтернативы, вы также можете использовать группу без захвата (?:…)
в этом случае:
(?:#{5})?<\w+>
Это обеспечивает тот же эффект группировки, ноне включается в \1
.
Ссылки
Смежные вопросы
Бонусный материал: как насчет ??
Стоит отметить, что вы можете использовать ??
, чтобы неохотно сопоставлять дополнительный элемент!
System.out.println("NOMZ".matches("NOMZ??"));
// "true"
System.out.println(
"NOM NOMZ NOMZZ".replaceAll("NOMZ??", "YUM")
); // "YUM YUMZ YUMZZ"
Обратите внимание, что Z??
является необязательным Z
, но это неохотно."NOMZ"
в целом все еще matches
шаблон NOMZ??
, но в replaceAll
, NOMZ??
может соответствовать только "NOM"
и не должен принимать дополнительный Z
, даже если он там есть.
В отличие от этого, NOMZ?
будет жадно соответствовать опциональному Z
: если он есть, он его примет.
System.out.println(
"NOM NOMZ NOMZZ".replaceAll("NOMZ?", "YUM")
); // "YUM YUM YUMZ"
Смежные вопросы