0

所以我有一个很长的输入字符串,我使用单个正则表达式提取了几位数据。输入是由客户端提供的,他们经常忘记重要的部分,这些部分不仅是正则表达式匹配所必需的(它们是),而且它们是这个正则表达式构建的数据库的组成部分。

我希望能够指出输入匹配开始失败的位置以及原因(向他们展示正则表达式接下来的期望)。

性能是个问题。正则表达式包含多个字段,因此将其分解为几个单独的正则表达式匹配可能会令人望而却步。

这是真实事物的缩减版:

^(?:(?P<doors>\d) Doors).*(?P<transmission>Automatic|Manual)

以及一些示例输入(和所需的输出):

"3 Doors blah blah blah Manual"  # match!
"Guadeloupe blah blah blah Sneezes"  # Reply: Missing doors
"2 Doors blah blah blah Psychic" # Reply: Missing transmission 
4

2 回答 2

2

您的问题太宽泛,无法由 Python 正则表达式引擎处理。您需要一个有限自动机引擎(更具体的 NFA),编写自己的解析器并输入字符串,看看它在哪里失败以及为什么失败。

或者,您可以使用PyParsing创建一个语法(您可以在PyParsing Wiki中找到大量示例),例如http://pyparsing.wikispaces.com/file/view/dfmparse.py 。如果您是 PyParsing 的新手,学习曲线会很陡峭,但是一旦您掌握了这个概念,实现您的意图将是轻而易举的事。

于 2013-09-13T09:15:06.203 回答
1

写一个解析器的想法(距离我的 JavaCC 时代已经过去了至少 10 年)让我觉得有点笨拙,而且我并不认为它比运行一堆编译的 REGEXES 更快......但是,我认为我想出了一个合适的解决方法。

我们首先使用单个正则表达式,如果失败,我们会淘汰增量的。如果失败率很低,这根本不应该是性能问题。

REGEXES = [
    (r'(?:(?P<doors>\d) Doors)', 'doors'),
    (r'.*(?P<transmission>Automatic|Manual)', 'transmission'),
]
FAILS = [(re.compile('^' + r[0], re.IGNORECASE), r[1]) for r in REGEXES]
MATCHER = re.compile('^' + ''.join([r[0] for r in REGEXES]), re.IGNORECASE)


# ... later ...

m = MATCHER.match(input)

if not m:
    working = input
    for r in FAILS:
        s = r[0].split(input)
        if len(s) > 1:
            working = s[-1]  # we use last group in the split
            continue
        # we have a problem here!!
        # we know the group (the regex and the label we gave it)
        # we can show the user what we're trying to match and against what
        return blah

# otherwise we can start working with m's groups.
于 2013-09-13T09:51:45.697 回答