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, и важно сохранить их в алфавитном порядке.

Таким образом, мой вопрос: Почему это лениво и как я фиксирую его?

10
задан AndersTornkvist 24 October 2011 в 21:25
поделиться

3 ответа

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

12
ответ дан 3 December 2019 в 18:33
поделиться

Согласно RegularExpressions.info , регулярные выражения стремятся . Следовательно, когда он проходит через ваше конвейерное выражение , он останавливается на первом твердом совпадении.

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

3
ответ дан 3 December 2019 в 18:33
поделиться

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

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

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

6
ответ дан 3 December 2019 в 18:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: