获取正则表达式的所有可能匹配(在python中)?

时间:2011-09-12 05:57:05

标签: python regex pattern-matching

我有一个正则表达式,可以多种重叠的方式匹配字符串。但是,它似乎只捕获字符串中的一个可能的匹配,我如何获得所有可能的匹配?我试过finditer但没有成功,但也许我错了。

我想解析的字符串是:

foo-foobar-foobaz

我正在使用的正则表达式是:

(.*)-(.*)

>>> s = "foo-foobar-foobaz"
>>> matches = re.finditer(r'(.*)-(.*)', s)
>>> [match.group(1) for match in matches]
['foo-foobar']

我想要比赛(foo和foobar-foobaz),但似乎只能获得(foo-foobar和foobaz)。

3 个答案:

答案 0 :(得分:5)

没问题:

>>> regex = "([^-]*-)(?=([^-]*))"
>>> for result in re.finditer(regex, "foo-foobar-foobaz"):
>>>     print("".join(result.groups()))
foo-foobar
foobar-foobaz

通过将第二个捕获括号放在lookahead assertion中,您可以捕获其内容,而不会在整体匹配中使用它。

我还使用[^-]*代替.*,因为该点也与您可能不想要的分隔符-匹配。

答案 1 :(得分:2)

这不是正则表达式引擎往往能够做到的。我不知道Python是否可以。 Perl可以使用以下内容:

local our @matches;
"foo-foobar-foobaz" =~ /
    ^(.*)-(.*)\z
    (?{ push @matches, [ $1, $2 ] })
    (*FAIL)
/xs;

使用以下技术可以使用多种语言的正则表达式引擎解决此特定问题:

my @matches;
while ("foo-foobar-foobaz" =~ /(?=-(.*)\z)/gsp) {
   push @matches, [ ${^PREMATCH}, $1 ];
}

${^PREMATCH}指的是正则表达式匹配之前的内容,而$1指的是第一个()匹配的内容。)

但是您可以在正则表达式引擎之外轻松解决这个特定问题:

my @parts = split(/-/, "foo-foobar-foobaz");
my @matches;
for (1..$#parts) {
   push @matches, [
      join('-', @parts[0..$_-1]),
      join('-', @parts[$_..$#parts]),
   ];
}

很抱歉使用Perl语法,但应该能够理解。翻译到Python欢迎。

答案 2 :(得分:1)

如果你想检测重叠的匹配,你必须自己实现它 - 基本上,对于一个字符串foo

  1. 查找以字符串索引i
  2. 开头的第一个匹配项
  3. 再次针对foo[i+1:]
  4. 运行匹配功能
  5. 对字符串的增量较短的剩余部分重复步骤1和2。
  6. 如果您使用任意长度的捕获组(例如(.*))会变得更加棘手,因为您可能不希望foo-foobaroo-foobar都匹配,所以你会必须做一些额外的分析才能使i比每场比赛更+1更远;你需要将它移动到第一个捕获组的值的整个长度,加上一个。