python正则表达式匹配搜索字符串

时间:2015-10-30 13:28:50

标签: python regex regex-lookarounds regex-greedy

我正在寻找一种方法来使python re模块或更新的正则表达式模块的finditer功能匹配特定模式的所有可能变体,重叠或其他。我知道使用lookaheads来获取匹配而不消耗搜索字符串,但我仍然只获得一个正则表达式,每个索引,我可以得到多个。

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

(?=A{2}[BA]{1,6}A{2})

所以在字符串中:

AABAABBAA

它应该能够匹配:

AABAA AABAABBAA AABBAA

但目前它只会匹配最后两个。我意识到这与[BA]{1,6}的贪婪有关。有没有办法让正则表达式从最懒惰到最贪婪的模式匹配?

3 个答案:

答案 0 :(得分:1)

您将无法使用finditer()或任何正常的导航方式。我管理它的唯一方法(使用Java而不是Python)是通过手动迭代源字符串的每个唯一子字符串(由起始位置和长度确定),以正常方式将正则表达式应用于每个子字符串(不是使用外观) ),并固定在两端。

Java的Matcher类使用region()方法提供了一种方便的方法。它允许您假装源的任何子串实际上都是整个事物,而不必生成新的String对象。并且matches()方法会自动锚定两端的匹配,因此您根本不需要修改正则表达式。

我很确定Python的re模块不支持这样的功能,但是在另一个模块中可能会有一些东西可以用来产生类似的效果(我不熟悉Python,所以这只是乐观)。我对regex模块更不熟悉,但它似乎支持所有其他风格的最甜蜜的功能,所以值得一看。

这是我的Java解决方案,以防您感兴趣:

public static void printAllMatches(String text, String regex)
{
  System.out.printf("%s results:%n", text);
  Matcher m = Pattern.compile(regex).matcher(text);
  int end = text.length();
  for (int i = 0; i < end; ++i)
  {
    for (int j = i + 1; j <= end; ++j) 
    {
      m.region(i, j);

      if (m.matches()) 
      {
        for (int k = 0; k < i; k++)
        {
          System.out.print(" ");
        }
        System.out.println(m.group());
      }   
    }   
  }   
}

输出:

AABAABBAA results:
AABAA
AABAABBAA
   AABBAA

答案 1 :(得分:1)

I realise it is to do with the greediness of the [BA]{1,6}. Is there a way to make the regex match everything from the laziest to the greediest possible pattern?

问题是双重的。

1. Regex engines will only match once at a character position.
2. There is not a regex construct of between lazy and greedy  
   it's either one or the other.  

跳过问题1.暂时..,

问题2
可能存在{1,6} 1,2,3,4,5或6匹配的情况 在给定位置的构造(字符)。

要解决该问题,您必须指定独立的{1},{2},{3},{4},{5},{6} 作为该位置的可选替换。
显然,范围 {1,6}无效。

Range 而言,可以指定它来找到
通过添加惰性修饰符{1,6}?来增加最小量 但这只能找到最小的数量,不多也不少。

最后,

问题1
当正则表达式引擎匹配时,总是向前推进当前位置
金额等于最后一场比赛的长度 在匹配的零长度断言的情况下,它人为地增加了 一个角色向前的位置。

因此,考虑到这两个问题,可以利用这些优势/劣势来实现这一目标 一个解决方法,并不得不忍受一些副作用。

<强>变通方法
将所有可能的替代方案放在一个位置作为要分析的断言。 某个位置的每个匹配将包含一个包含变体的组列表 因此,如果您匹配6个可能的变体组中的3个变体,则具有值的组将是变体。

如果没有任何组具有值,则在该位置找不到变体 不会发生任何变体,因为所有断言都是可选的 为了避免在这些特定位置进行不必要的匹配,最后一个 条件可用于不报告这些内容。 (即(?(1)|(?(2)|(?!)))等。)。

让我们使用您的范围示例作为示例 我们将在末尾使用条件来验证匹配的组,
但没有它就可以完成。
_注意使用此范围示例导致重叠相同的
最终匹配中的值。这确实确保了唯一的匹配 一个位置(下面的例子显示了如何避免这种情况)。

 # (?=(A{2}[BA]{1,6}?A{2}))?(?=(A{2}[BA]{1,6}A{2}))?(?(1)|(?(2)|(?!)))

 (?=
      (                             # (1 start)
           A{2}
           [BA]{1,6}? 
           A{2} 
      )                             # (1 end)
 )?
 (?=
      (                             # (2 start)
           A{2}
           [BA]{1,6} 
           A{2} 
      )                             # (2 end)
 )?
 (?(1)
   |  (?(2)
        |  (?!)
      )
 )

输出:

 **  Grp 1 -  ( pos 0 , len 5 ) 
AABAA  
 **  Grp 2 -  ( pos 0 , len 9 ) 
AABAABBAA  

-------------

 **  Grp 1 -  ( pos 3 , len 6 ) 
AABBAA  
 **  Grp 2 -  ( pos 3 , len 6 ) 
AABBAA  

相同,但没有范围问题 在这里,我们明确定义了独特的结构 请注意每个位置的唯一值。

 # (?=(A{2}[BA]{1}A{2}))?(?=(A{2}[BA]{2}A{2}))?(?=(A{2}[BA]{3}A{2}))?(?=(A{2}[BA]{4}A{2}))?(?=(A{2}[BA]{5}A{2}))?(?=(A{2}[BA]{6}A{2}))?(?(1)|(?(2)|(?(3)|(?(4)|(?(5)|(?(6)|(?!)))))))

 (?=
      (                             # (1 start)
           A{2}
           [BA]{1} 
           A{2} 
      )                             # (1 end)
 )?
 (?=
      (                             # (2 start)
           A{2}
           [BA]{2} 
           A{2} 
      )                             # (2 end)
 )?
 (?=
      (                             # (3 start)
           A{2}
           [BA]{3} 
           A{2} 
      )                             # (3 end)
 )?
 (?=
      (                             # (4 start)
           A{2}
           [BA]{4} 
           A{2} 
      )                             # (4 end)
 )?
 (?=
      (                             # (5 start)
           A{2}
           [BA]{5} 
           A{2} 
      )                             # (5 end)
 )?
 (?=
      (                             # (6 start)
           A{2}
           [BA]{6} 
           A{2} 
      )                             # (6 end)
 )?

 (?(1)|(?(2)|(?(3)|(?(4)|(?(5)|(?(6)|(?!)))))))

输出:

 **  Grp 1 -  ( pos 0 , len 5 ) 
AABAA  
 **  Grp 2 -  NULL 
 **  Grp 3 -  NULL 
 **  Grp 4 -  NULL 
 **  Grp 5 -  ( pos 0 , len 9 ) 
AABAABBAA  
 **  Grp 6 -  NULL 

------------------

 **  Grp 1 -  NULL 
 **  Grp 2 -  ( pos 3 , len 6 ) 
AABBAA  
 **  Grp 3 -  NULL 
 **  Grp 4 -  NULL 
 **  Grp 5 -  NULL 
 **  Grp 6 -  NULL 

最后,您需要做的就是在每场比赛中抓住抓取组 使用值,并将它们放入数组中。

答案 2 :(得分:-2)

此正则表达式正确匹配3个字符串:

AABAA AABAABBAA AABBAA

((^(AA){1}(BAA)$){1})|(((AA){1}(BB){1}(AA){1}$){1})

如果你想在字符串&#34; AABAABBAA&#34;中搜索这些子字符串。使用python你可以使用方法&#34;搜索&#34; :

re.search('AABAABB','AABAABBAA')
re.search('AABAABBAA','AABAABBAA')
re.search('AABBAA','AABAABBAA')