Предполагая, что у меня есть:
StartTest NoInclude EndTest StartTest Include EndTest
и я использую:
/StartTest(?!NoInclude)[\s\S]*?EndTest/g
Почему я сопоставляю обе группы?
Пример Regexr: http://regexr.com/3db8m
Вы не выполняете матч с помощью NoInclude
если NoInclude
появляется сразу после StartTest
. Вам нужен умеренный жадный токен :
(?s)StartTest(?:(?!(?:Start|End)Test|NoInclude).)*EndTest ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
См. Демо-версию regex
StartTest
выражение соответствует StartTest
, затем соответствует любому тексту, который не является StartTest
, EndTest
или NoInclude
, вплоть до EndTest
.
Потому что *
жадный, он сделает .
как можно больше. Отрицательный outlook заставит его прекратить сопоставление в местах, где следуют следующие альтернативы:
(?:Start|End)Test
– StartTest
или EndTest
NoInclude
– просто NoInclude
. ПРИМЕЧАНИЕ . (?s)
является встроенным модификатором (эквивалентом флага RegexOptions.Singleline
), который модифицирует .
поведение в шаблоне, что также соответствует LF (новые строки). Без этого модификатора (или без RegexOptions.Singleline
) точка соответствует любому символу, но новой RegexOptions.Singleline
.
ПРИМЕЧАНИЕ 2. Если вы тестируете регулярное выражение вне среды исходного кода, убедитесь, что вы используете соответствующий тестер для вашего аромата регулярного выражения. regexr.com поддерживает только JavaScript-вкус, regex101.com поддерживает JS, PCRE и Python, а также поддерживает RegexStorm.net/RegexHero.net. Есть еще много тестировщиков, читайте, что они поддерживают, а что не первое.
Вот демонстрация C # :
using System; using System.IO; using System.Text.RegularExpressions; using System.Linq; public class Test { public static void Main() { var input = "StartTest\n NoInclude\nEndTest\n\nStartTest\n Include\nEndTest"; var regex = new Regex(@"(?s)StartTest(?:(?!(?:Start|End)Test|NoInclude).)*EndTest"); var results = regex.Matches(input).Cast() .Select(p => p.Value) .ToList(); Console.WriteLine(string.Join("\n", results)); } }