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