Использование жадного подхода в регулярном выражении последовательности слов
У меня есть регулярное выражение, которое превращает следующий текст
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: проверьте еще раз свой код, так как движок должен жадно совпадать по умолчанию.