соответствует n -ному вхождению (исключая последнее вхождение) - PullRequest
0 голосов
/ 25 октября 2018

У меня есть вопрос о регулярном выражении.Я не знаю, почему я не могу сделать следующее.

Пример предложения:

"This is a test string with five t's"

Используемое мной регулярное выражение:

^(.*?(?=t)){3}

Я хочу, чтобы регулярное выражение совпадалоследующее.

"This is a test s"

Но это не работает, кто-нибудь знает почему?

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Дело в том, что весь шаблон группы .*?(?=t) может соответствовать пустой строке.Он останавливается перед первым t и не может «перепрыгнуть», потому что остается там, где он есть, когда совпадает шаблон прогнозирования (непотребляющий шаблон).

Вы не можете делать это так, вы должны потреблять (и перемещать индекс регулярных выражений) хотя бы один символ.

Альтернативное решение для этого конкретного случая -

^(?:[^t]*t){2}[^t]*

См. regex demo , ^(?:[^t]*t){2}[^t]* соответствует началу строки (^), затем использует два вхождения ({2}) любых символов, кроме t ([^t]*), затемс t, а затем снова использует два вхождения ({2}) любых символов, отличных от t.

Или, общее решение для случая (если t является строкой из нескольких символов):

^(?:.*?t){2}(?:(?!t).)*

См. еще одну демонстрацию регулярных выражений .Шаблон (?:.*?t){2} соответствует двум вхождениям любых 0+ символов, как можно меньше, вплоть до первого t, а затем (?:(?!t).)* соответствует любому типу символов 0+, который не запускает последовательность символов t,

0 голосов
/ 25 октября 2018

Как говорит @ CertainPerformance , .* будет соответствовать нулю или более символов в шаблоне, но вы используете его ленивую версию .*?.Ленивая версия квантификатора будет соответствовать как можно меньшему количеству символов.С квантификатором, который соответствует пустой строке, это всегда приведет к совпадению нулевой длины.

Вам нужно использовать вместо + квантификатор`, чтобы предотвратить совпадение пустой строки.

Демонстрация с Python:

>>> import re
>>> s = "This is a test string with five t's"
>>> r = r'^(.+?(?=t)){3}'
>>> re.match(r, s)
<_sre.SRE_Match object; span=(0, 16), match='This is a test s'>
...