首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用正则表达式找到最短的重叠匹配?

如何使用正则表达式找到最短的重叠匹配?
EN

Stack Overflow用户
提问于 2010-01-28 00:49:35
回答 9查看 7.4K关注 0票数 16

对于regex来说,我还是个新手。我试图找到与特定模式匹配的最短文本字符串,但如果最短模式是较大匹配的子串,则会遇到问题。例如:

代码语言:javascript
运行
复制
import re
string = "A|B|A|B|C|D|E|F|G"
my_pattern = 'a.*?b.*?c'

my_regex = re.compile(my_pattern, re.DOTALL|re.IGNORECASE)
matches = my_regex.findall(string)

for match in matches:
    print match

打印:

代码语言:javascript
运行
复制
A|B|A|B|C

但我想让它回来:

代码语言:javascript
运行
复制
A|B|C

有没有办法做到这一点,而不必遍历每个匹配,以查看它是否包含匹配的子字符串?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-09-26 19:49:10

与这里的大多数其他答案相反,这可以在使用带有capturing grouppositive lookahead assertion的单个正则表达式中完成

代码语言:javascript
运行
复制
>>> my_pattern = '(?=(a.*?b.*?c))'
>>> my_regex = re.compile(my_pattern, re.DOTALL|re.IGNORECASE)
>>> matches = my_regex.findall(string)
>>> print min(matches, key=len)
A|B|C

findall()将返回所有可能的匹配项,因此您需要min()来获取最短的匹配项。

它是如何工作的:

  • 我们不匹配这个正则表达式中的任何文本,只匹配字符串中的位置(正则表达式引擎在尝试匹配时逐步执行)。
  • 在每个位置,正则表达式引擎都会向前看,看看您的正则表达式在这个位置是否匹配。
  • 如果是,则会被捕获组捕获。
  • 如果不是,就不会。
  • 在这两种情况下,正则表达式引擎都会前进一个字符,并重复这个过程,直到字符串结束。
  • 由于先行断言不占用任何字符,因此将找到所有重叠的匹配项。
票数 15
EN

Stack Overflow用户

发布于 2010-01-28 01:00:41

不是的。Perl返回最长的、最左边的匹配,同时遵守非贪婪的量词。恐怕你得循环一遍。

编辑:是的,我意识到我在上面提到了Perl,但我相信Python也是如此。

票数 1
EN

Stack Overflow用户

发布于 2010-01-28 02:25:40

这可能是一个有用的sexegers应用程序。正则表达式匹配偏向于最长、最左边的选择。使用非贪婪的量词,比如在.*?中绕过最长的部分,并颠倒输入和模式都可以绕过最左边的匹配语义。

考虑以下根据需要输出A|B|C的程序:

代码语言:javascript
运行
复制
#! /usr/bin/env python

import re

string = "A|B|A|B|C|D|E|F|G"
my_pattern = 'c.*?b.*?a'

my_regex = re.compile(my_pattern, re.DOTALL|re.IGNORECASE)
matches = my_regex.findall(string[::-1])

for match in matches:
    print match[::-1]

另一种方法是创建一个更严格的模式。假设你不想重复已经看到的字符:

代码语言:javascript
运行
复制
my_pattern = 'a[^a]*?b[^ab]*?c'

您的示例是通用的和人为的,但如果我们对您正在使用的输入有更好的想法,我们就可以提供更好、更有帮助的建议。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2148700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档