【问题标题】:Find out till where a regex satisfies a sentence找出正则表达式满足句子的位置
【发布时间】:2019-03-30 21:15:39
【问题描述】:

我有一些句子和一个正则表达式。是否有可能找出我的句子满足正则表达式的位置。例如,将我的句子视为MMMV,将正则表达式视为M+V?T*Z+。现在正则表达式直到 M+V? 满足句子,正则表达式的剩余部分是 T*Z+ 这应该是我的输出。

我现在的方法是将正则表达式分解为单个部分并将其存储在一个列表中,然后通过连接前 n 个部分进行匹配,直到句子匹配。例如,如果我的正则表达式是M+V?T*Z+,那么我的列表就是['M+', 'V?', 'T*', 'Z+']。然后我首先在循环中匹配我的字符串M+,其次是M+V?,依此类推,直到找到完全匹配,然后将剩余的列表作为输出。下面是代码

            re_exp = ['M+', 'V?', 'T*', 'Z+']
            for n in range(len(re_exp)):
                re_expression = ''.join(re_exp[:n+1])
                if re.match(r'{0}$'.format(re_expression), sentence_language):
                    return re_exp[n+1:]

是否有更好的方法来实现这一点可能是通过使用一些解析库等。

【问题讨论】:

  • 正则表达式有多复杂?它可以有组、字符组、反向引用、前瞻等吗?
  • 如果正则表达式非常简单,如您的示例所示,您可能甚至可以编写一个非常简单的自定义正则表达式解析器/匹配器。特别是如果正则表达式的连续部分处理不同的字符(例如,没有V?V+),那么这甚至应该贪婪地工作,没有任何回溯。
  • 正则表达式很简单。但我在编写自定义函数时唯一考虑的是随着正则表达式大小的增加,速度差异和最终情况的处理。如果我可以调整 re 本身以获取输出或使用其他解析库会很有帮助
  • 也许,不是连接正则表达式的部分然后匹配整个字符串,您可以只匹配一个部分,然后将下一部分匹配到字符串的其余部分,即切掉匹配的前缀正则表达式的第一个“术语”。
  • 如果一个字符串匹配M+V?,那么它也匹配M+V?T*,因为T*可以匹配零个字符。所以很难看出假设的部分匹配器如何将M+V? 报告为部分匹配。

标签: python regex parsing


【解决方案1】:

您可以使用() 将组括在正则表达式中。例如:M+V?(T*Z+),你想要的输出存储在正则表达式的第一组中。

我知道问题是 python,但在这里你可以看到正则表达式的作用:

const regex = /M+V?(T*Z+)/;
const str = `MMMVTZ`;
let m = regex.exec(str);

console.log(m[1]);

【讨论】:

  • 这种方法的问题是我事先不知道() 会出现在哪里。可以这样想,我需要告诉用户在他/她输入一些句子后应该发生什么。句子可以是MMMMMMV等。所以输出在每种情况下都会有所不同。
【解决方案2】:

假设您的正则表达式相当简单,没有组、反向引用、前瞻等,例如就像你的情况一样,按照\w[+*?]? 的模式,你可以先把它分成几部分,就像你已经做的那样。但是,您可以通过切掉已经匹配的部分来单独测试每个部分,而不是迭代地连接这些部分并将它们与整个字符串进行匹配。

def match(pattern, string):
    res = pat = ""
    for p in re.findall(r"\w[+*?]?", pattern):
        m = re.match(p, string)
        if m:
            g = m.group()
            string = string[len(g):]
            res, pat = res + g, pat + p
        else:
            break
    return pat, res

例子:

>>> for s in "MMMV", "MMVVTTZ", "MTTZZZ", "MVZZZ", "MVTZX":
>>>     print(*match("M+V?T*Z+", s))
...
M+V?T* MMMV
M+V?T* MMV
M+V?T*Z+ MTTZZZ
M+V?T*Z+ MVZZZ
M+V?T*Z+ MVTZ

但是,请注意,在最坏的情况下,有一个长度为 n 的字符串和一个由 n 部分组成的模式,每个部分只匹配一个字符,这仍然需要 O(n²) 来重复切片字符串.

另外,如果两个连续的部分大约是同一个字符,这可能会失败,例如a?a+b应该等同于a+b)不会匹配ab,而只会匹配aab,因为单个a已经被a?“消耗”了。

您可以通过为这种非常简化的正则表达式编写自己的非常简单的正则表达式匹配器将复杂性降低到 O(n),但在一般情况下,这可能不值得,甚至更慢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 2021-12-01
    • 2019-12-24
    • 1970-01-01
    相关资源
    最近更新 更多