Regex 匹配第n次出现(排除最后一次出现)

Regex 匹配第n次出现(排除最后一次出现),regex,regex-lookarounds,Regex,Regex Lookarounds,我有一个关于regex的问题。我不知道为什么我不能做到以下几点 "This is a test s" 例句: "This is a test string with five t's" 我使用的正则表达式: ^(.*?(?=t)){3} 我希望正则表达式与以下内容匹配 "This is a test s" 但是它不起作用,有人知道为什么吗?正如所说,*将匹配模式中的零个或多个字符,但您使用它的延迟版本*?。 量词的惰性版本将使其匹配尽可能少的字符。 对于匹配空字符串的量词,这将始终导致零

我有一个关于regex的问题。我不知道为什么我不能做到以下几点

"This is a test s"
例句:

"This is a test string with five t's"
我使用的正则表达式:

^(.*?(?=t)){3}
我希望正则表达式与以下内容匹配

"This is a test s"
但是它不起作用,有人知道为什么吗?

正如所说,
*
将匹配模式中的零个或多个字符,但您使用它的延迟版本
*?
。 量词的惰性版本将使其匹配尽可能少的字符。 对于匹配空字符串的量词,这将始终导致零长度匹配

您需要使用
+
量词来代替`,以防止空字符串匹配

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'>
>>重新导入
>>>s=“这是一个有五个t的测试字符串”
>>>r=r'^(+?(?=t)){3}'
>>>重新匹配(r,s)

这里的要点是整个
*?(?=t)
组模式可以匹配一个空字符串。它在第一个
t
之前停止,并且无法“跳转”,因为当前瞻模式(非消费模式)匹配时,它仍保持在原来的位置

不能这样做,必须使用(并移动regex索引)至少一个字符

这个具体案例的另一个解决方案是

^(?:[^t]*t){2}[^t]*
请参见,
^(?:[^t]*t){2}[^t]*
匹配字符串的开头(
^
),然后使用两次出现的(
{2}
)除
t
[^t]*
)以外的任何字符(
[^t]*
),然后再次使用两次出现的(
{code>{2}
)除
以外的任何字符

或者,一般情况下的解决方案(如果
t
是多字符字符串):


看。
(?:.*t){2}
模式匹配任何0+字符的两次出现,尽可能少,直到第一次
t
,然后
(?:(?!t)。*
匹配任何不启动
t
字符序列的字符,0+出现

*
匹配零个或多个上一个标记,您想要
+
而不是(对于一个或多个)我的答案对您有帮助吗?这里的要点是整个
*?(?=t)
组模式可以匹配空字符串。它在第一个
t
之前停止,并且无法“跳转”,因为当前瞻模式匹配时,它仍保持在原来的位置。不能这样做,必须使用(并移动regex索引)至少一个字符。这个具体案例的另一个解决方案是
^(?:[^t]*t){2}[^t]*
。或者,一个通用的案例解决方案:
^(?:*?t){2}(?:(?!t)。*
非常感谢大家。我在你发帖的时候读了你的答案,但还是回复了你。因为我对regex是个新手。我对正则表达式的理论知之甚少,例如正则表达式索引,正则表达式的每一步是如何进行的。所以我花了两天的时间来弄清楚你说了什么,然后试着把你的答案弄错。现在我似乎明白了一些事情,但不是很深刻。经过大量测试,我认为@Wiktor Stribiżew的答案更好,非常感谢。帮助我提高正则表达式的技能。如果你不理解这里的任何特定部分,请在我的答案下面加一个词。谢谢你,右腿,你帮我了解了一点正则表达式的理论D@Cam很高兴它有帮助!然后你可以接受这个答案,从而将你的问题标记为ansewered:)为什么在这里添加非捕获组(?)?我只知道非捕获组的用法,它不作为替换的结果。@Cam我使用它是因为我不需要访问与此组匹配的文本。如果您只需要对一些模式进行分组以量化它们的序列,那么使用捕获组是没有意义的,因为只有最后一次出现才会保存为组值(除非它是.NET或Python PyPi regex)。了解更多关于。