Регулярное выражение с повторяющимися символами и длиной в .NET - PullRequest
0 голосов
/ 02 мая 2018

У меня есть регулярное выражение, где мне нужно сопоставить часть буквы в захвате. Буквы могут быть длиной 1-3 символа и должны быть одинаковыми. Не ABC, но A, AA или AAA работает, а затем число. Я могу только соответствовать A1 в настоящее время, но не AA1. Я использую .NET для Regex.

^(?<pool>([A-Z])\1{0,2})(?<number>(100)|[1-9]\d?)$

A1
AA2
AAA3
B5
CC7

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Небольшое дополнение и исправление к аккуратному ответу Аллана:

3-й шаблон не соответствует должным образом в обработчике регулярных выражений .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 regex и PCRE, например, в PHP.

С первого взгляда работает так же:

Захваты с круглыми скобками автоматически нумеруются слева направо право на основе порядка открывающих скобок в регулярном выражение, начиная с одного **. Захват, который нумеруется как текст соответствует шаблону регулярного выражения.

Ref. MSDN: группировка конструкций в регулярных выражениях

Итак, пока

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

В .NET, однако,

неназванные группы захвата сначала назначенные номера, считая их открывающие скобки слева направо, пропуская все названные группы. После этого именованные группы присваивают числа, которые следуют, считая открывающие скобки названных групп слева направо.

На самом деле это объясняется на той же странице регулярные выражения.info / named.html , ссылка на которую содержится в ответе.

Простой пример:

Для соответствия 1a1 в .NET вы можете использовать

(?<named>(\d)a)\1

Для сопоставления аналогичным образом в PHP вы должны использовать \ 2 вместо

(?<named>(\d)a)\2

Мораль:

Смешивать именованные и пронумерованные группы захвата не рекомендуется, потому что вкусы несовместимы в том, как нумеруются группы.

Кстати:

Я подготовил этот паттерн \b(?<pool>([A-Z])\1{0,2})(?<number>(\d{1,2}(?!\d)|100))\b, но затем переключил внимание на разницу, изложенную выше. Вы также можете играть с \1 против \2 в связанной демонстрационной версии.

0 голосов
/ 02 мая 2018

Подойдет ли вам следующее регулярное выражение?

\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?))$

DEMO

Дайте мне знать, если это работает для вас, также посмотрите:

https://www.regular -expressions.info / named.html

И последнее, но не менее важное: если вы хотите, чтобы именованная группа захвата <pool> соответствовала и захватывала A, AA или AAA, вы можете использовать:

^(?<pool>([A-Z])\2{0,2})(?<number>(100|[1-9]\d?))$

DEMO

Только с именованными группами захвата:

^(?<pool>(?<letter>[A-Z])\k<letter>{0,2})(?<number>(100|[1-9]\d?))$

DEMO

...