Подтвердить что ты не робот

Regex: сопоставление с группами в другом порядке без повторения группы

Скажем, у меня есть две строки:

XABY
XBAY

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

X(AB|BA)Y

Однако у меня есть случай, когда A и B являются сложными строками, и я ищу способ избежать необходимости указывать каждый из них дважды (по обе стороны от). Есть ли способ сделать это (это, по-видимому, проще, чем указать их дважды)?

Спасибо

4b9b3361

Ответ 1

X(?:A()|B()){2}\1\2Y

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

Помните, что это зависит от недокументированного поведения регулярных выражений, поэтому нет гарантии, что он будет работать в вашем регулярном выражении - и если это произойдет, нет никакой гарантии, что он будет продолжать работать, поскольку этот аромат развивается. Но, насколько я знаю, он работает в каждом вкусе, который поддерживает обратные ссылки. (EDIT: он не работает в JavaScript.)

РЕДАКТИРОВАТЬ:. Вы говорите, что используете группы имен для захвата частей матча, что добавляет много визуального беспорядка в регулярное выражение, если не реальную сложность. Ну, если вы используете регулярные выражения .NET, вы можете использовать простые нумерованные группы для "флажков". Здесь упрощенный пример, который находит и выделяет кучу строк в течение месяца, не зная их внутреннего порядка:

  Regex r = new Regex(
    @"(?:
        (?<MONTH>Jan|Feb|Mar|Apr|May|Jun|Jul|Sep|Oct|Nov|Dec)()
        |
        (?<DAY>\d+)()
      ){2}
      \1\2",
    RegexOptions.IgnorePatternWhitespace);

  string input = @"30Jan Feb12 Mar23 4Apr May09 11Jun";
  foreach (Match m in r.Matches(input))
  {
    Console.WriteLine("{0} {1}", m.Groups["MONTH"], m.Groups["DAY"]);
  }

Это работает, потому что в .NET присутствие названных групп не влияет на упорядочение неименованных групп. Именованные группы имеют присвоенные им номера, но эти числа начинаются после последней из неименованных групп. (Я знаю, что это кажется безнадежно сложным, но есть веские причины для этого.)

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

Ответ 2

Вы можете хранить фигуры регулярных выражений в переменных и делать:

A=/* relevant regex pattern */
B=/* other regex pattern */
regex = X($A$B|$B$A)Y

Таким образом, вам нужно только указать каждое регулярное выражение один раз в своей строке, что упростит его поддержку.

Sidenote: вы пытаетесь найти перестановки, что хорошо, потому что вы смотрите только на 2 подподразделения. Но если вы хотите добавить третий (или четвертый), ваши перестановки регулярных выражений резко возрастают - (abc | acb | bac | bca | cab | cba) - или еще хуже. Если вам нужно пойти по пути перестановок, там есть хорошее обсуждение этого вопроса на fooobar.com/questions/425166/.... Это для перестановки букв, а решения используют awk/bash/perl, но это по крайней мере дает вам отправную точку.

Ответ 3

Если есть несколько строк, с любыми символами там, вам будет лучше:

X(.)+Y

Только числа, тогда

X([0-9])+Y

Только буквы

X([a-zA-Z])+Y

Буквы и цифры

X([a-zA-Z][0-9])+Y

Ответ 4

попробуйте это

X((A|B){2})Y