Я думал, что по умолчанию мой 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
Теперь я понимаю, что мог заставить это работать на этот небольшой пример, если бы я просто отсортировал ключевые слова по убыванию длины, но
Таким образом, мой вопрос: Почему это лениво и как я фиксирую его?
Лень и жадность применимы только к кванторам (?
, *
, +
, {мин., Макс.}
). Чередования всегда совпадают по порядку и пробуют первое возможное совпадение.
Согласно RegularExpressions.info , регулярные выражения стремятся . Следовательно, когда он проходит через ваше конвейерное выражение , он останавливается на первом твердом совпадении.
Я бы порекомендовал хранить все ключевые слова в массиве или списке, а затем генерировать отсортированное по конвейеру выражение, когда оно вам нужно. Вам нужно будет сделать это только один раз, если ваш список ключевых слов не изменится. Просто сохраните сгенерированное выражение в каком-либо синглтоне и верните его при выполнении регулярного выражения.
Похоже, что вы пытаетесь сломать слово. Для этого вам нужно, чтобы все выражение было правильным, а ваше нынешнее выражение таковым не является. Попробуйте вместо него вот это...
new Regex(@"\b(in|int|into|internal|interface)\b");
В "\b" сказано, что нужно искать границы слов, и это совпадение нулевой ширины. Это зависит от локали, но в общем случае это означает пробелы и пунктуацию. Будучи совпадением нулевой ширины, оно не будет содержать символ, который заставил механизм regex обнаружить границу слова.