Использование жадного подхода в регулярном выражении последовательности слов

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

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 остановится, как только будет оценена альфа, даже если за ней следует бета.

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


@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()))

2 ответа

Решение

Описание

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

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

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

введите описание изображения здесь

пример

Введите текст

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

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

Другим способом будет выделение общих подвыражений из выражений совпадений, например

\b(alpha(\ beta)?\b

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

Другие вопросы по тегам