Первый .*
изначально соответствует всей строке. Затем механизм регулярных выражений определяет, нужно ли ему отступать, чтобы соответствовать остальным регулярным выражениям. Но (?<h>((dog)*))
и (?(h)(?<dog>(.*)))
могут по закону совпадать с нулевыми символами, поэтому не требуется никакого возврата (в отношении .*
). Попробуйте использовать не жадный .*?
в этой части.
РЕДАКТИРОВАТЬ (в ответ на дополнительную информацию, размещенную в ответе ниже): Хорошо, замена первого .*
ненадежным .*?
оказывает влияние, только не тот, который вы хотите. Если раньше все, что было после слова «круто», захватывалось в группе <cool>
, то теперь оно захватывается в группе <dog>
Вот что происходит:
После того, как слово «круто» сопоставлено, (?<cool>(.*?))
изначально ничего не соответствует (противоположность жадному поведению), а (?<h>((dog)*))
пытается сопоставить. Эта часть всегда будет успешной независимо от того, где она пробована, потому что она может соответствовать либо "собаке", либо пустой строке. Это означает, что условное выражение в (?(h)...)
всегда будет иметь значение true
, поэтому оно идет вперед и сопоставляет остальную часть ввода с (?<dog>(.*))
.
Насколько я понимаю, вы хотите сопоставить все после слова "круто" в именованной группе <cool>
, если строка не содержит слова "собака"; тогда вы хотите захватить все после «собаки» в именованной группе <dog>
. Для этого вы пытаетесь использовать условное , но это не совсем правильный инструмент. Просто сделайте это:
string pattern = @"cool (?<cool>.*?) (dog (?<dog>.*))?$";
Ключ здесь - $
в конце; это заставляет не жадного .*?
продолжать сопоставление, пока не достигнет конца строки. Поскольку он не жадный, он пытается найти следующую часть регулярного выражения, (dog (?<dog>.*))
, перед тем как использовать каждый символ. Если есть слово «собака», остальная часть строки будет поглощена (?<dog>.*)
; если нет, то регулярное выражение все еще успешно, потому что ?
делает всю эту часть необязательной.