| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Общие вопросы по .NET и C# > Alternation Constructs в .NET Regexp |
| Автор: FiMa1 28.8.2008, 14:13 |
| Добрейшего времени суток, друзья. Столкнулся со следующей проблемой: Имеем следующую теорию http://msdn.microsoft.com/en-us/library/36xybswe(VS.71).aspx, пытаюсь использовать '(?(expression)yes|no)' регулярное выражение. Входной текст: "abcdefg", пишу (?(abc)defg|"") - получаю 'No Matches' (конструктор регулярных выражений 'RAD Software Regular Expression Designer 1.4.7'). Если кто-нибудь сталкивался с подобным или знает в чем дело, помогите, пожалуйста. |
| Автор: Bishop 28.8.2008, 15:37 |
| FiMa1, Вы хотите "abc" использовать как шаблон, а оно воспринимается как name. Укажите явно: (?(?<=abc)defg|""). http://msdn.microsoft.com/en-us/library/bs2twtah.aspx. http://www.pcre.ru/docs/php/text/stdsyntax/ — разделы Утверждения и Условные подмаски. |
| Автор: FiMa1 28.8.2008, 16:24 | ||
Bishop, большое спасибо! Я пробежался глазами по приведенным ссылкам, пока не уяснил для себя, что можно считать "именем"? Никогда до этого сталкивался с этим понятием. (?(name)yes|no) Matches the "yes" part if the named capture string has a match; otherwise, matches the "no" part. The "no" part can be omitted. If the given name does not correspond to the name or number of a capturing group used in this expression, the alternation construct is interpreted as an expression test (described in the preceding row of this table). Не подскажите вкратце, если есть минутка. Был бы еще больше признателен |
| Автор: Bishop 28.8.2008, 19:15 | ||||||||
FiMa1, группы (подмаски), т.е. выражения в скобках можно именовать, тогда к ним можно будет обращаться не по номерам, а по этим именам.
В случае альтернатив:
И это наиболее понятный способ их использования. Я похоже ошибся в прошлом посте:
Т.е. все работает, но анализ идет четко с начала строки, как будто там не abc, а ^abc.
А этот результат объяснить не могу |
| Автор: Bishop 29.8.2008, 01:51 | ||||||||
| source777, В первой из трёх нижних строк выполняется yes. А в остальных всё тоже правильно, то есть не "глючно"
Я почему-то подумал (и похоже, ты тоже), что эта конструкция работает по логике if-then-else: если expression истинно, то ищется шаблон yes, иначе шаблон no. Но это не так. Выражение "yes" — это вся часть (expression)yes. А (expression), если не указано явно, это (?=expression). Фактически, это сокращенная запись, которую можно развернуть в:
И тогда все ясно с примерами: Место (abc) === (?=abc) в строке находится "(_здесь_)abcdefgh"
Потому что:
|
| Автор: FiMa1 29.8.2008, 08:59 |
| Bishop, source777, большое спасибо за участие! Теперь понятно с именами и почему я с ними не сталкивался, я не использовал регулярные выражения непосредственно в коде на C#. |
| Автор: source777 29.8.2008, 10:54 | ||||||
Однако, всё равно остались невыясненные моменты, например,
Казалось бы, поскольку IsMatch == true, то в Match.Value всегда должно быть "yes", в независимости от "no" - части, однако это не так... Причём если использовать в качестве входной строки "yesno", то так и будет, однако такая жёсткая привязка в началу строки не всегда подходит, в качестве воркэраунда насколько я выяснил сработает:
|
| Автор: Bishop 29.8.2008, 19:45 | ||||||||||||
source777,
Не, не так. Оно не ищет условие, идет последовательный анализ строки и, если условие ложно, а часть NO в этой позиции находит совпадение, разбор прекращается. Смотри:
Причем (yes) это сокращенная запись утверждения (?=yes). Разбор начинается с начала строки: на символе "a" (?=yes) ложно — переход к части NO; .* в этой позиции совпадает со всей строкой — это результат.
Здесь разбор идет так: "a" — (?=yes) ложно, часть NO в текущей позиции не совпадает; "b" — тоже; "c" — тоже; "y" — (?=yes) истинно, (?=yes)yes совпадает — это результат. И правильный вариант:
Этапы разбора: "a" — (?=.*yes) истинно, но (?=.*yes)yes не совпадает, .* пропускается; "b" — тоже; "c" — тоже; "y" — (?=.*yes) истинно, (?=.*yes)yes совпадает — это результат. Тогда всё ясно с непонятным результатом выражения из моего позапрошлого поста:
Разбор: "a" — (?=abc) истинно, но (?=abc)f не совпадает, .* пропускается; "b" — (?=abc) ложно, .* совпадает с "bcdefgh" — это результат. Не вся строка, т.к. "a" уже пропущена, а разбор без особой нужды в обратную сторону не идёт. Может я ошибаюсь на счёт внутренней работы regex engine, но концептуально оно вот так. Т.е. не ищется совпадение expression по всей строке (как мы думали), оно вычисляется на общих основаниях по мере разбора строки. От простой альтернативы отличается тем, что пока условие истинно совпадения в блоке NO не ищутся. Вот:
В описании этапов под буквами подразумеваются Zero-width позиции перед ними. Пытался объяснить, надеюсь не запутал ещё больше |
| Автор: source777 30.8.2008, 16:19 |
| Bishop, спасибо, более менее прояснилась ситуация |