У меня есть регулярное выражение, в котором мне нужно сопоставить буквенную часть в захвате. Буквы могут иметь длину 1-3 символа и должны быть одной и той же буквой. Нет ABC, но работает A, AA или AAA, за которыми следует число. В настоящее время я могу сопоставить только A1, а не AA1. Я использую .NET для регулярного выражения.
^(?<pool>([A-Z])\1{0,2})(?<number>(100)|[1-9]\d?)$
A1
AA2
AAA3
B5
CC7
Нравится Этот?
Надеюсь, я не опоздала на вечеринку. :) - wp78de 1 час назад
Подойдет ли вам следующее регулярное выражение?
\b(([A-Z])\2{0,2}(?:100|[1-9]\d?))\b
Он принимает: A1 AA2 AAA3 B5 CC7
и не соответствует AAAA4
или ABC123
.
Если вы хотите использовать для них Именованные группы захвата и обратные ссылки, вы можете изменить свое регулярное выражение на:
^(?<pool>([A-Z]))\k<pool>{0,2}(?<number>(100|[1-9]\d?))$
Сообщите мне, работает ли это для вас, также посмотрите:
https://www.regular-expressions.info/ named.html
И последнее, но не менее важное: если вы хотите, чтобы названная группа захвата <pool>
соответствовала и захватила A
, AA
или AAA
, вы можете использовать:
^(?<pool>([A-Z])\2{0,2})(?<number>(100|[1-9]\d?))$
Только с именованными группами захвата:
^(?<pool>(?<letter>[A-Z])\k<letter>{0,2})(?<number>(100|[1-9]\d?))$
AA не соответствует <pool>, просто A
@MikeFlynn: позволь мне исправить это для тебя
@MikeFlynn: как насчет последнего регулярного выражения?
@ Аллан хороший. Однако для третьего шаблона в качестве обратной ссылки требуется \1
. Смотрите мой ответ.
Этот ответ работает в онлайн-тестере, но по какой-то причине не работает в .NET. Любая подсказка, почему?
Небольшое дополнение и исправление к аккуратному ответу Аллана:
Третий шаблон не соответствует правильно в механизме регулярных выражений .NET, потому что обратная ссылка \2
должна быть пронумерована иначе, чем в показанном шаблоне PCRE (с использованием regex101).
Вместо \2
должен быть \1
:
^(?<pool>([A-Z])\1{0,2})(?<number>(100|[1-9]\d?))$
Этот dotnetfiddle демонстрирует проблему: вместо ~ 300 тестовых примеров, которые я сгенерировал, совпадают только первые 100 (из A1-A100).
Вы можете проверить это самостоятельно, используя regexstorm, тестер регулярных выражений .NET.
Почему? Существует тонкая разница между тем, как именованные группы захвата, смешанные с обычными группами захвата, упоминаются в регулярных выражениях .NET и PCRE, например в PHP.
На первый взгляд это работает одинаково:
Captures that use parentheses are numbered automatically from left to right based on the order of the opening parentheses in the regular expression, starting from one**. The capture that is numbered zero is the text matched by the entire regular expression pattern.
Ref. MSDN: группирование конструкций в регулярных выражениях
Так что пока
most flavors number both named and unnamed capturing groups by counting their opening parentheses from left to right. Adding a named capturing group to an existing regex still upsets the numbers of the unnamed groups
Однако в .NET
unnamed capturing groups are assigned numbers first, counting their opening parentheses from left to right, skipping all named groups. After that, named groups are assigned the numbers that follow by counting the opening parentheses of the named groups from left to right.
Фактически это объясняется на той же странице regular-expressions.info/ named.html, ссылка на которую есть в ответе.
Простой пример:
Чтобы соответствовать 1a1
в .NET, вы можете использовать
(?<named>(\d)a)\1
Для сопоставления аналогичным образом в PHP вам придется вместо этого использовать \ 2
(?<named>(\d)a)\2
Мораль:
Mixing named and numbered capturing groups is not recommended because flavors are inconsistent in how the groups are numbered.
КСТАТИ:
Я подготовил этот шаблон \b(?<pool>([A-Z])\1{0,2})(?<number>(\d{1,2}(?!\d)|100))\b
, но затем переключил внимание на разницу, описанную выше. Вы также можете поиграть с \1
против \2
в связанной демоверсии.
не могли бы вы добавить язык программирования, который используете?