如何在python中找到所有可能的正则表达式匹配?

时间:2014-05-14 12:08:42

标签: python regex parentheses

我正在尝试使用python及其正则表达式查找所有可能的单词/标记对或其他嵌套组合。

sent = '(NP (NNP Hoi) (NN Hallo) (NN Hey) (NNP (NN Ciao) (NN Adios)))'

def checkBinary(sentence):
    n = re.findall("\([A-Za-z-0-9\s\)\(]*\)", sentence)
    print(n)

checkBinary(sent)

Output:
['(NP (NNP Hoi) (NN Hallo) (NN Hey) (NNP (NN Ciao) (NN Adios)))']

寻找:

['(NP (NNP Hoi) (NN Hallo) (NN Hey) (NNP (NN Ciao) (NN Adios)))', 
 '(NNP Hoi)', 
 '(NN Hallo)',
 '(NN Hey)', 
 '(NNP (NN Ciao) (NN Adios))',
 '(NN Ciao)',
 '(NN Adios)']

我认为正则表达式公式可以找到嵌套的括号词/标签对,但它并没有返回它们。我该怎么做?

2 个答案:

答案 0 :(得分:31)

实际上不可能通过使用正则表达式来实现这一点,因为正则表达式表达由 常规 语法定义的语言,可以通过非有限确定性自动机来解决,匹配由状态表示;然后,为了匹配嵌套的括号,你需要能够匹配无数个括号,然后有一个具有无限数量状态的自动机。

为了能够应对这种情况,我们使用所谓的下推自动机,用于定义 上下文免费 语法。

Chomsky's hierarchy

因此,如果您的正则表达式与嵌套的括号不匹配,那是因为它表示以下自动机并且与输入中的任何内容都不匹配:

Regular expression visualization

Play with it

作为参考,请查看麻省理工学院关于该主题的课程:

因此,有效解析字符串的方法之一是为嵌套括号(pip install pyparsing首先)构建语法:

>>> import pyparsing
>>> strings = pyparsing.Word(pyparsing.alphanums)
>>> parens  = pyparsing.nestedExpr( '(', ')', content=strings)
>>> parens.parseString('(NP (NNP Hoi) (NN Hallo) (NN Hey) (NNP (NN Ciao) (NN Adios)))').asList()
[['NP', ['NNP', 'Hoi'], ['NN', 'Hallo'], ['NN', 'Hey'], ['NNP', ['NN', 'Ciao'], ['NN', 'Adios']]]]

N.B。:存在一些使用下推实现嵌套括号匹配的正则表达式引擎。默认的python re引擎不是其中之一,但存在一个替代引擎,称为regexpip install regex),它可以进行递归匹配(这使得引擎上下文无关),cf this code snippet

>>> import regex
>>> res = regex.search(r'(?<rec>\((?:[^()]++|(?&rec))*\))', '(NP (NNP Hoi) (NN Hallo) (NN Hey) (NNP (NN Ciao) (NN Adios)))')
>>> res.captures('rec')
['(NNP Hoi)', '(NN Hallo)', '(NN Hey)', '(NN Ciao)', '(NN Adios)', '(NNP (NN Ciao) (NN Adios))', '(NP (NNP Hoi) (NN Hallo) (NN Hey) (NNP (NN Ciao) (NN Adios)))']

答案 1 :(得分:2)

现代语言中使用的正则表达式不代表常规语言。 zmo说得对,语言Theroy中的常规语言由有限状态自动机表示,但使用任何类型的回溯的正则表达式,如现代语言中使用的捕获组,外观等等,不能用语言中已知的FSA表示理论。如何使用DFA或偶数和NFA表示类似(\ w +)\ 1的模式?

您正在寻找的正则表达式可能是这样的(只匹配两个级别):

(?=(\((?:[^\)\(]*\([^\)]*\)|[^\)\(])*?\)))

我在http://regexhero.net/tester/

上对此进行了测试

匹配在捕获的组中:

1:(NP(NNP Hoi)(NN Hallo)(NN Hey)(NNP(NN Ciao)(NN Adios))

1:(NNP Hoi)

1:(NN Hallo)

1:(NN嘿)

1 :( NNP(NN Ciao)(NN Adios))

1:(NN Ciao)

1:(NN Adios)