我会使用什么样的正则表达来匹配它?

时间:2010-06-30 18:17:45

标签: python regex

我有几个字符串如下所示:

<some_text> TAG[<some_text>@11.22.33.44] <some_text>

我想从这一行获取ip_address并且只获取ip_address。 (为了这个例子,假设ip地址将始终采用这种格式xx.xx.xx.xx)

编辑:恐怕我不清楚。

字符串看起来像这样:

<some_text> TAG1[<some_text>@xx.xx.xx.xx] <some_text> TAG2[<some_text>@yy.yy.yy.yy] <some_text>

请注意,'some_text'可以是可变长度。我需要将不同的正则表达式关联到不同的标记,以便在调用r.group()时,将返回ip地址。在上面的例子中,正则表达式不会有所不同,但这是一个不好的例子。

到目前为止,我尝试过的正则表达式已经不足够了。

理想情况下,我想要这样的事情:

r = re.search('(?<=TAG.*@)(\d\d.\d\d.\d\d.\d\d)', line)

其中line的格式为上面指定的格式。但是,这不起作用,因为您需要具有固定宽度的后视断言。

此外,我已尝试过非捕获组:

r = re.search('(?<=TAG\[)(?:.*@)(\d\d.\d\d.\d\d.\d\d)', line)

但是,我不能使用它,因为r.group()将返回some_text@xx.xx.xx.xx

我知道r.group(1)只返回ip地址。不幸的是,我写的脚本要求我的所有正则表达式在调用r.group()后返回正确的结果。

我可以在这种情况下使用什么样的正则表达式?

代码在python中。

注意:所有some_text都可以是可变长度

4 个答案:

答案 0 :(得分:2)

尝试re.search('(?<=@)\d\d\.\d\d\.\d\d\.\d\d(?=\])', line)

事实上,如果要检查的字符串中唯一出现的xx.xx.xx.xx格式位于这些IP地址部分,re.search('\d\d\.\d\d\.\d\d\.\d\d', line)可能会为您提供所需的内容。

编辑:正如我的评论中所述,要查找字符串中所需的所有模式,您只需执行re.findall(pattern_to_match, line)。因此,在这种情况下,re.findall('\d\d\.\d\d\.\d\d\.\d\d', line)(或更一般地,re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', line))。

编辑2:根据您的评论,这应该有效(tagname是您当前想要的IP地址的标记。)

r = re.search(tagname + '\[.+?@(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', line)

然后你就像psmears所说的那样用r.group("ip")来引用它。

......实际上,有一种简单的方法可以使正则表达式更加简洁。

r = re.search(tagname + r'\[.+?@(?P<ip>(?:\d{1,3}\.?){4})', line)

事实上,你甚至可以这样做:

r = re.findall('(?P<tag>\S+)\[.+?@(?P<ip>(?:\d{1,3}\.?){4})', line)

哪个会返回一个包含标签及其关联IP地址的列表,因此如果您想要从其中找到不同标签的IP地址,则不必重新检查任何一个字符串。相同的字符串。

......事实上,进一步走得更远(更远?),你可以做到以下几点:

r = dict((m.group("tag"), m.group("ip")) for m in re.finditer('(?P<tag>\S+)\[.+?@(?P<ip>(?:\d{1,3}\.?){4})', line))

或者在Python 3中:

r = {(m.group("tag"), m.group("ip")) for m in re.finditer('(?P<tag>\S+)\[.+?@(?P<ip>(?:\d{1,3}\.?){4})', line)}

然后r将是一个dict,标签为键,IP地址为各自的值。

答案 1 :(得分:1)

你为什么要使用群组或者根本不看? re.search('TAG\[.*@(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]')有什么问题?

答案 2 :(得分:1)

我认为不可能这样做 - r.group()将始终返回匹配的整个字符串,因此您不得不使用lookbehind,正如您所说的必须是固定宽度。

相反,我建议修改你正在编写的脚本。我猜你有一整套匹配的正则表达式,并且你不想为每一个指定“这个使用r.group(0)”,“这个使用r.group(3) )“等等。

在这种情况下,您可以使用Python的命名组工具:您可以在正则表达式中命名一个组,如下所示:

(?P<name>CONTENTS)

然后检索与r.group("name")匹配的内容。

我建议你在脚本中做的是:匹配正则表达式,然后测试是否设置了r.group("usethis")。如果是这样 - 使用那个;如果不是 - 那么像以前一样使用r.group()。

通过在正则表达式中指定组名usethis,您可以应对这种尴尬的情况 - 但您的其他正则表达不必知道或关心。

答案 3 :(得分:0)

差不多但我觉得你需要在开始时将。*更改为。 *?,因为你可能在一行上有多个TAG(我相信 - 正如示例中所示)

re.search('TAG(\d+)\[.*?@(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})]')

标签ID将位于第一个反向引用中,IP地址将位于第二个反向引用