2013-06-27 7 views
1

У меня есть регулярное выражение, которое превращает следующий текстИспользуя жадный подход в последовательности слов регулярное выражение

alpha beta + gamma delta - epsilon phi

в

<ref4> + <ref45> - <ref11> 

с эталонами быть внутренними идентификаторами. Я строй регулярного выражения из следующего кода

EncodeRegex = new Regex("\b(?<nom>" + // word boundary 
String.Join("|", Things.Select(t => Regex.Escape(t.Name)).ToArray()) + 
")\b", // word boundary 
RegexOptions.IgnoreCase); 

Пример для приведенного выше текста может быть

\b(alpha\ beta|gamma\ delta|epsilon\ phi)\b 

где «альфа-бета» и совместно являются текстовыми блоками, которые я должен признать. Затем я заменяю значения текстовых блоков своими ссылками с помощью специального MatchEvaluator.

У меня проблема; если у меня есть два текстовых блока A и B, где A - префикс B, регулярное выражение зависит от порядка A и B. \b(alpha|alpha\ beta)\b остановится, как только будет оценен Alpha, даже если за ним последует Beta.

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


@Anirudh: Я использую следующий код

EncodeRegex.Replace(s, new MatchEvaluator(m => Things.Where(Function(r) r.Name.ToUpper() == m.Groups("nom").Value.ToUpper()).Select(Function(r) "<" & r.Reference & ">").FirstOrDefault())) 
+0

и какой код вы используете, чтобы заменить его. – Anirudha

+0

отредактирован для добавления кода замены – samy

ответ

2

Описание

На основе вашего образца текста, известны разделители между вашими группами, так что вы могли бы просто использовать предпросмотр для проверки разделителя, как в следующем выражении это будет препятствовать короткий префиксу от завершения матча.

Regex: (^|[+-]\s)(alpha|alpha\ beta)(?=\s[+-]|$)

Заменить: $1~~~new value~~~

enter image description here

Пример

ввода текста

alpha beta + gamma delta - epsilon phi 
alpha + alpha beta + gamma delta - epsilon phi 

Пример кода

Imports System.Text.RegularExpressions 
Module Module1 
    Sub Main() 
    Dim sourcestring as String = "replace with your source string" 
    Dim replacementstring as String = "$1~~~new value~~~" 
    Dim matchpattern as String = "(^|[+-]\s)(alpha|alpha\ beta)(?=\s[+-]|$)" 
    Console.Writeline(regex.Replace(sourcestring,matchpattern,replacementstring,RegexOptions.IgnoreCase OR RegexOptions.Multiline)) 
    End Sub 
End Module 

ввода После замены

~~~new value~~~ + gamma delta - epsilon phi 
~~~new value~~~ + ~~~new value~~~ + gamma delta - epsilon phi 
+0

+1 Хорошая идея ... –

+0

Отлично! Я стараюсь забыть взгляд, раскалываясь по известной грамматике. Два вопроса: почему бы этот подход не работал со словом в качестве второго параметра (см. Http://regexr.com?35cpl)? и из любопытства, какой инструмент вы использовали для создания графика для оценки регулярных выражений? – samy

+0

Граница слов не работает, потому что в вашем выражении отсутствует разделитель + или -. Поскольку этот пример не всегда имеет разделители, окруженные пробелами, я думаю, вы хотели бы использовать что-то вроде '\ b \ s * (? = [+/* -] | $)'. Путем перемещения его из взгляда вперед вы разрешаете пробелы в конце строки. Точный подход действительно зависит от точного эффекта, который вы ищете. С ними за пределами группы захвата 1 вы эффективно обрезаете пространство из захвата или можете даже переместить \ b и \ s в строку захвата, чтобы включить его. –

0

вы можете захотеть попробовать справа налево соответствие, если ни один из ваших моделей не является суффиксом другого шаблона см MSDN tutorial и reference для деталей.

Другой способ пойти будет заключаться в том, чтобы разложить общие подвыражения из ваших совпадающих выражений, например.

\b(alpha(\ beta)?\b 

пс: пересчитайте ваш код, так как двигатель должен соответствовать жадности по умолчанию.

+0

Так как в шаблонах может быть некоторый префикс, я бы ошибался в безопасности и предполагал, что может быть и некоторый суффикс. Факторинг подвыражений выглядит как overkill и упорядочивает шаблоны, но это хорошая идея, я буду иметь в виду – samy