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