Regex ведет себя ленивым, должен быть жадным

Я думал, что по умолчанию мой Regex будет демонстрировать желаемое поведение, но это не так в следующем коде:

 Regex keywords = new Regex(@"in|int|into|internal|interface");
 var targets = keywords.ToString().Split('|');
 foreach (string t in targets)
    {
    Match match = keywords.Match(t);
    Console.WriteLine("Matched {0,-9} with {1}", t, match.Value);
    }

Выход:

Matched in        with in
Matched int       with in
Matched into      with in
Matched internal  with in
Matched interface with in

Теперь я понимаю, что мог бы заставить его работать для этого небольшого примера, если бы я просто сортировал ключевые слова по убыванию, но

  • Я хочу понять, почему это не работает, как ожидалось, и
  • Реальный проект, над которым я работаю, содержит в Regex еще много слов, и важно держать их в алфавитном порядке.

Итак, мой вопрос: почему это лень и как мне это исправить?

3 ответа

Решение

Лень и жадность распространяется только на квантификаторы (?, *, +, {min,max}). Чередования всегда совпадают по порядку и пробуют первое возможное совпадение.

Похоже, вы пытаетесь сломать слова. Для этого вам нужно, чтобы все выражение было правильным, а текущее - нет. Попробуйте это вместо этого..

new Regex(@"\b(in|int|into|internal|interface)\b");

"\ B" говорит, что соответствует границам слов, и соответствует совпадению с нулевой шириной. Это поведение зависит от локали, но в целом это означает пробелы и знаки препинания. Будучи совпадением с нулевой шириной, он не будет содержать символ, который заставил механизм регулярных выражений обнаружить границу слова.

Согласно http://www.regularexpressions.info/, регулярные выражения стремятся. Поэтому, когда оно проходит через ваше переданное по конвейеру выражение, оно останавливается на первом сплошном совпадении.

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

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