记事本++正则表达式分组捕获

64

我有这样的文本文件:

ххх.prontube.ru
salo.ru
bbb.antichat.ru
yyy.ru
xx.bb.prontube.ru
zzz.com
srfsf.jwbefw.com.ua

尝试使用以下正则表达式删除所有子域:

Find:    .+\.((.*?)\.(ru|ua|com\.ua|com|net|info))$
Replace with: \1

收到:

prontube.ru
salo.ru
antichat.ru
yyy.ru
prontube.ru
zzz.com
com.ua
为什么最后一行变成了com.ua而不是jwbefw.com.ua
4个回答

67

这个不需要前后环视:

查找: [a-zA-Z0-9-.]+\.([a-zA-Z0-9-]+)\.([a-zA-Z0-9-]+)$ 替换为: \1\.\2

它找到至少有两个点和最后两个点之后只有字母、数字和破折号的内容;然后用最后两部分替换它。在我看来,更直观。

那个前导的xxx出了点问题。它似乎不是纯ASCII编码。为了回答这个问题,我假设这只是这个网站上有趣的东西,而不代表您的真实数据。

错误

有趣的是,在这里我之前有一个错误的答案获得了很多赞成票。所以我认为我应该保留它:

查找: [a-zA-Z0-9-]+\.([a-zA-Z0-9-]+)\.(.+)$ 替换为: \1\.\2

它只是查找带有至少两个句点的主机名,并将其替换为第一个句点后面的所有内容。


10

.+部分尽可能匹配。尝试使用.+?,它会捕获最少的内容,允许com.ua选项进行匹配。


1
.+?\.([\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之后第一个句号会匹配,然后在第一组(.*?)中匹配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))$

1

搜索内容:.+?\.(\w+\.(?:ru|com|com\.au))
替换为:$1

看看上面的图片,正则表达式捕获指的是什么
这样你就不需要解释正则表达式了……

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接