Regex для захвата необязательной группы в середине блока ввода - PullRequest
1 голос
/ 03 января 2009

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

Предположим, у меня есть такой ввод:

Some text %interestingbit% lots of random text lots and lots more %anotherinterestingbit%
Some text %interestingbit% lots of random text OPTIONAL_THING lots and lots more %anotherinterestingbit%
Some text %interestingbit% lots of random text lots and lots more %anotherinterestingbit%

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

Подобный RegEx соответствует только блокам с OPTIONAL_THING в нем (и именованный захват работает):

%interestingbit%.+?((?<OptionalCapture>OPTIONAL_THING)).+?%anotherinterestingbit%

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

%interestingbit%.+?((?<OptionalCapture>OPTIONAL_THING))?.+?%anotherinterestingbit%

Но я считаю, что хотя это соответствует всем 3 блокам, именованный захват (OptionalCapture) во всех них пуст! Как мне заставить это работать?

Обратите внимание, что в каждом блоке может быть много текста, включая символы новой строки, поэтому я вставил ". +?" а не что-то более конкретное. Я использую регулярные выражения .NET, тестирую с The Regulator.

Ответы [ 3 ]

2 голосов
/ 04 января 2009

Мои мысли сходны с идеей Нико. Тем не менее, я бы предложил разместить 2-й. +? внутри необязательной группы вместо первой, как показано ниже:

%interestingbit%.+?(?:(?<optionalCapture>OPTIONAL_THING).+?)?%anotherinterestingbit%

Это позволяет избежать ненужного возврата. Если первый. +? находится внутри необязательной группы, и OPTIONAL_THING не существует в строке поиска, регулярное выражение не будет знать об этом, пока не достигнет конца строки. Затем потребуется откат, возможно, совсем немного, чтобы сопоставить% другой интересный бит%, который, как вы сказали, всегда будет существовать.

Кроме того, поскольку OPTIONAL_THING, когда он существует, всегда будет перед% otherинтересным битом%, текст после него также является необязательным и более естественно вписывается в необязательную группу.

0 голосов
/ 03 января 2009

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

%interestingbit%(?:(.+)(?<optionalCapture>OPTIONAL_THING))?(.+?)%anotherinterestingbit%

Сначала существует группа без захвата, которая соответствует .+OPTIONAL_THING или ничего. Если совпадение найдено, внутри есть именованная группа, которая захватывает OPTIONAL_THING для вас. Остальное захвачено с .+?%anotherinterestingbit%.

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

  • $ 1: текст перед OPTIONAL_THING или ничего
  • $ 2 или $ optionCapture: OPTIONAL_THING или ничего
  • $ 3: текст после OPTIONAL_THING или, если OPTIONAL_THING не найден, полный текст между% интересным битом% и% другим интересным битом%

Это три матча, которые вы ищете?

0 голосов
/ 03 января 2009

Почему у вас есть дополнительный набор скобок?

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

%interestingbit%.+?(?<OptionalCapture>OPTIONAL_THING)?.+?%anotherinterestingbit%

Или, может быть, это будет работать:

%interestingbit%.+?(?<OptionalCapture>OPTIONAL_THING|).+?%anotherinterestingbit%

В этом примере группа захватывает OPTIONAL_THING или ничего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...