@"(?is)<p>(?>(?:(?!</?p>).)*)</p>"
(?:(?!</?p>).)*
соответствует одному символу за раз, после того как мы проверили, что он не является частью тега <p>
или </p>
.
(?>...)
представляет собой атомную группу ; это предотвращает возврат назад, который, как мы знаем, был бы бессмысленным.
(?is)
- это альтернативный механизм для указания модификаторов соответствия - в этом случае IgnoreCase и Singleline (последний в случае, если между тегами есть перевод строки или возврат каретки, что будет избыточным, но вы действительно сказали, что это не совсем так. HTML).
Кстати, <
и >
не имеют особого значения в регулярных выражениях, поэтому нет необходимости избегать их. Фактически, в некоторых разновидностях вы можете придать им особые значения, избегая их: \<
и \>
означают «начало слова» и «конец слова» соответственно. Но в регулярных выражениях .NET обратные слеши просто беспорядочные.