Notepad ++正则表达式组捕获

时间:2013-07-01 22:12:27

标签: regex notepad++

我有这样的txt文件:

ххх.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 个答案:

答案 0 :(得分:45)

这无需环顾四周:

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

它会找到至少有2个句点的内容,并且在最后两个句点之后只能找到字母,数字和短划线;然后用最后两部分替换它。在我看来更直观。

领导xxx会有一些有趣的事情发生。它似乎不是纯ASCII。为了这个问题,我将假设这个网站只是一些有趣的东西而不能代表您的真实数据。

不正确

有趣的是,我之前在这里得到的答案不正确,积累了很多赞成票。所以我认为我应该保留它:

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

它只找到一个至少包含2个句点的主机名,然后用第一个点后的所有内容替换它。

答案 1 :(得分:9)

.+部分尽可能匹配。请尝试使用.+?代替它,它将尽可能少地捕获,允许com.ua选项匹配。

答案 2 :(得分: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之后的第一个句段将匹配,然后在组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))$

答案 3 :(得分:0)

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

看上图,regex capture指的是什么
它的颜色使您不再需要正则表达式解释......

enter image description here