.+?\.([\w-]*?\.(?:ru|ua|com\.ua|com|net|info))$
这个答案仍然使用原始问题正在查看的特定域名。由于某些 TLD(顶级域)中有一个句点,理论上您可以拥有一个包含多个子域的列表,如果它适用于您的数据集,则在正则表达式中将 TLD 列入白名单是一个好主意。当前的两个答案(从 2013 年开始)都无法正确处理“xx.bb.prontube.ru”和“srfsf.jwbefw.com.ua”之间的区别。
下面是为什么这个 psnig 的原始正则表达式没有按预期工作的快速解释:
这+
是贪婪的。
.+
将在捕获所有内容的行尾一直拉到右边,然后向后(向左)从这里寻找匹配项:
(ru|ua|com\.ua|com|net|info)
使用srfsf.jwbefw.com.ua正则表达式引擎将首先失败匹配a
,然后它将标记向左移动一个位置以查看“ua”此时,ua
正则表达式(第二个选项)是匹配的。
引擎不会继续寻找“com.ua”,因为“.ua”满足了该要求。
Niet the Dark Absol 的回答告诉正则表达式“懒惰”
.+?
将匹配任何字符(至少一个),然后尝试找到正则表达式的下一部分。如果失败,它将推进令牌,.+
再匹配一个字符,然后再次评估正则表达式的其余部分。
.+? 最终将消耗:srfsf.jwbefw在匹配句点之前,然后匹配com.ua。
但是, 的实施?
也会产生问题。
添加问号会首先使 .+ 变得懒惰,但随后会导致 group1 匹配bb.prontube.ru而不是prontube.ru
这是因为 bb 之后的第一个时期将匹配,然后在第 1 组内(.*?)
将匹配bb.prontube。\.(ru|ua|com\.ua|com|net|info))$
比赛前.ru
为避免这种情况,请将第三组从 更改为(.*?)
,([\w-]*?)
这样它就不会捕获。只有字母和数字,或破折号。
结果正则表达式:
.+?\.(([\w-])*?\.(ru|ua|com\.ua|com|net|info))$
请注意,您不需要捕获除第一个之外的任何组。添加 ?: 使 TLD 选项不被捕获。
最后一次变更:
.+?\.([\w-]*?\.(?:ru|ua|com\.ua|com|net|info))$