Что эквивалентно оператору сброса ветки (?|), найденному в php (pcre) на С#?

Следующее регулярное выражение будет соответствовать «суббота» или «воскресенье»: (?:(Sat)ur|(Sun))day

Но в одном случае обратная ссылка 1 заполнена, а обратная ссылка 2 пуста, а в другом случае наоборот.

PHP (pcre) предоставляет хороший оператор "?|" который обходит эту проблему. Предыдущее регулярное выражение станет (?|(Sat)ur|(Sun))day. Так что пустых обратных ссылок не будет.

Есть ли эквивалент в С# или какой-то обходной путь?


person Stephan    schedule 21.03.2011    source источник
comment
Вместо этого вы можете использовать (?:(Sat(?=ur)|Sun(?!ur))(?:ur)?)day. :)   -  person Gumbo    schedule 21.03.2011
comment
@Gumbo, почему за тобой не следует Сан? Регулярное выражение немного сложно...   -  person Stephan    schedule 21.03.2011
comment
в противном случае может совпасть Sunurday. Что немного похоже на ошибку, которую я совершил (на которую вы указали :))   -  person Bart Kiers    schedule 21.03.2011
comment
В противном случае он также будет соответствовать Sunurday.   -  person Gumbo    schedule 21.03.2011


Ответы (3)


.NET не поддерживает оператор сброса ветки, но поддерживает именованные группы и позволяет повторно использовать имена групп без ограничений (чего не делает ни один другой вариант, насколько мне известно). Итак, вы можете использовать это:

(?:(?<abbr>Sat)ur|(?<abbr>Sun))day

...и сокращенное имя будет сохранено в Match.Groups["abbr"].

person Alan Moore    schedule 21.03.2011
comment
Да, это путь (в случае регулярного выражения). Аккуратный. - person Bart Kiers; 21.03.2011
comment
Perl позволяет повторно использовать именованные группы в одном и том же шаблоне. Нет никаких ограничений. Это также позволяет вам получить список совпавших именованных групп. - person tchrist; 28.04.2011
comment
с PCRE вы можете использовать модификатор (?J) (должен быть помещен в первую позицию в шаблоне), который позволяет использовать именованные группы с тем же именем. (Это раз и навсегда, вы не можете отключить его позже). - person Casimir et Hippolyte; 08.04.2014
comment
Этот ответ был добавлен в Часто задаваемые вопросы о регулярных выражениях переполнения стека в разделе "Группы". - person aliteralmind; 10.04.2014
comment
regex Python позволяет повторно использовать имена групп, но, конечно он также знает оператор сброса ветки. - person AXO; 25.05.2020

должно быть возможно объединить backref1 и backref2.
Поскольку одна из них всегда пуста, а строка, совмещенная с пустой, остается одной и той же строкой...

с вашим регулярным выражением (?:(Sat)ur|(Sun))day и заменой $1$2
вы получите Sat вместо Saturday и Sun вместо Sunday.

 regex (?:(Sat)ur|(Sun))day
 input    | backref1 _$1_ | backref2 _$2_ | 'concat' _$1$2_
 ---------|---------------|---------------|----------------
 Saturday | 'Sat'         | ''            | 'Sat'+'' = Sat
 Sunday   | ''            | 'Sun'         | ''+'Sun' = Sun

вместо чтения backref1 или backref2 просто прочитайте оба результата и объедините результат.

person bw_üezi    schedule 21.03.2011
comment
я бы предпочел получать результаты напрямую без каких-либо манипуляций с входной строкой (например, оператор сброса ветвления). - person Stephan; 21.03.2011
comment
@Стефан, я не понимаю твоего комментария? Я не думаю, что манипулировал входной строкой. Я просто указал, что вы можете объединить группу1 и группу2 из результата регулярного выражения без каких-либо изменений в регулярном выражении. - person bw_üezi; 21.03.2011
comment
@bw_üezi, можете ли вы отредактировать свой ответ с подробным примером кода, потому что я до сих пор не понимаю вашего решения. - person Stephan; 21.03.2011
comment
+1 это кажется намного лучше, чем усложнять регулярное выражение только для того, чтобы получить желаемое значение в одной обратной ссылке. - person juharr; 21.03.2011
comment
@juharr спасибо за понимание моего решения KISS ;-) - person bw_üezi; 21.03.2011
comment
@bw_üezi Я большой фанат KISS, группы и принципа. - person juharr; 21.03.2011
comment
@bw_üzei хорошо, ваше решение простое, но требует двух шагов. - person Stephan; 24.03.2011

Вы можете использовать оператор сброса ветки:

(?|foo(bar)|still(life)|(like)so)

Это установит только первую группу, независимо от того, какая ветвь соответствует.

person tchrist    schedule 21.03.2011
comment
И здесь я подумал, что StackOverflow — это то место, где нужно искать качество, а не количество ответов. - person Robert Synoradzki; 20.12.2017