具有完全重叠结果的正则表达式/匹配引擎和"光标"操作

时间:2017-02-10 19:41:07

标签: python regex algorithm parsing markup

我正在寻找与正则表达式引擎有些相似的东西,但它允许完全重叠的结果,并允许操纵内部游标"当引擎返回匹配时。

正常的正则表达方式:

假设您使用各种"替代品":item1|item2|item3使用正常的正则表达式,并使用findallfinditer来获取所有匹配项。在输入字符串中的某个位置,引擎可以匹配任何这些替代方案。一旦找到,光标就会在匹配结束后立即前进到索引,并继续寻找任何替代方案。即使这些替代品中的两个或更多可能与初始光标位置处的字符串匹配,也只返回一个:

import re
input_string = 'foobar'
compiled = re.compile('foobar|foo|bar')
compiled.findall(input_string)

# 'foobar'  

我想要的(1):

我希望他们全部归还。像这样:

import muchneededregexthing
input_string = 'foobar'
compiled = muchneededregexthing.compile('foobar|foo|bar')
searcher = compiled.create_searcher(input_string)
while not searcher.reached_end():
    match = searcher.search() # increments searcher's internal cursor 
                              # to after the end of the match
    print(match.string, match.span())

# foobar (0,6)
# foo (0,3)
# bar (3,6)

我还想要的东西(2):

我希望能够修改搜索者的光标,以便我可以根据运行时发生的事情来操纵结果(' foobar'匹配,' foo&# 39;并且' bar'分别不重要。)

import muchneededregexthing
input_string = 'foobarkitten'
compiled = muchneededregexthing.compile('foobar|foo|bar|kitten')
searcher = compiled.create_searcher(input_string)
while not searcher.reached_end():
    match = searcher.search() # increments searcher's internal cursor 
                              # to after the end of the match
    print(match.string, match.span())
    if match.string == 'foobar':
        searcher.advance_cursor(match.end())

# foobar (0,6)
# kitten (6,12)

我不能使用(最有可能):

  • str.find:我需要标记(markdown / wiki / etc)解析器的正则表达式。在任何时候,都可能需要寻找许多不同的元素。使用str.find我需要使用标记支持的每个元素搜索整个文档。该语言过于复杂,无法将文档细分为块,如#34;标题块","段块"等等。

  • re:除非我神奇地支持我需要的东西,否则我不能使用它,原因如下:正则表达式是有限的,你不能匹配你喜欢的任何东西。然而,他们的属性对我的情况很有用。我打算分两个阶段进行匹配:正则表达式为元素提供了可能的匹配。然后咨询智能函数/方法,以确定可能的匹配是否与良好匹配。如果是这样,伟大的,提前光标。如果没有,请点击foobar并自行提供foobar个机会。

非常欢迎您的想法。我很确定我需要这些功能。到目前为止,我最好的想法是编写我自己的muchneededregexthing模块,支持C / C ++中的大多数正则表达式语法,所以不要担心我会忽视你的想法。

编辑1:请求标记

标记元素,因此需要匹配的标记,通过插件定义和引入。因此,框架本身不包含任何标记。我可以简单地将插件的标记与正则表达式匹配并完成它,但我想至少探索选项并尝试允许更大范围的标记标记,而不是使用正则表达式支持的标记标记。 。例如,如果它们的关系是数字应该是字符串的一些数字表示,那么如何匹配string:numbera:0是有效令牌,但a:1不是。然而,b:1bc:28(1 * 26 + 2 * 1)。

对于此示例,插件可以提供正则表达式,例如([a-z]{1,5})([0-9]{1,5})。然后,算法将匹配传递给特殊函数,该函数计算第一组的数值并将其与第二组的值进行比较。如果这些值匹配,那么插件将处理文档的这一部分。如果没有,它将返回并尝试让另一个插件在文档中处理此索引。

2 个答案:

答案 0 :(得分:0)

您可以使用纯Python轻松实现此功能如果您保证不会在相同位置匹配两个不同的模式,并且长度相同。

如果pattern是已编译的正则表达式,则pattern.search(str, start)将查找从start开始的匹配项,pattern.search(str, start, length)将查找从start开始的匹配项最多length

所以做一个搜索。前进到匹配的地方。检查是否需要。如果没有,那就决定扔掉它。使用相同的模式和较短的长度在同一点进行另一次搜索。如果它不匹配,或者匹配得更远,则推进光标。

答案 1 :(得分:0)

对于那些寻求这个问题答案的未来流浪者:我最近遇到了hyperscan,它确实在寻找我想要的东西。它在C语言中,但是有一个Python port(我没有测试端口,但是本地C版本效果很好)。

尽管大多数正则表达式引擎在输入字符串的给定偏移量上仅匹配一个子模式,但是Hyperscan将报告针对每个偏移量匹配的所有子模式。另请参见hyperscan semantics

相关问题