正则表达式从词性解析树中提取名词短语



我正在尝试从斯坦福POS解析树中提取所有三个单词名词短语。基本上,任何看起来像:

(NP (TAG WORD) (TAG WORD) (TAG WORD))

或:

(NP (TAG WORD) (TAG (TAG WORD) (TAG WORD)))

解析树的样子如下:

(ROOT (SQ (VBZ Is) (NP (DT this)) (NP (DT an) (NN asthma) (NN attack)) (. ?)))

当我做这个正则表达式时,它会提取正确的 3 字名词短语:

threeWordNounPhrases = full.scan(/(NP ([^()]+ [^()]+) ([^()]+ [^()]+))/)
# => "(NP (DT an) (NN asthma) (NN attack))"

但是,这不适用于以下情况:

(ROOT (SQ (NNP Should) (NP (PRP I)) (VP (VB watch) (NP (NP (NNP Game)) (PP (IN of) (NP (NNP Thrones)))) ) (. ?)))

哪个应该返回:

(NP (NP (NNP Game)) (PP (IN of) (NP (NNP Thrones))))

具体来说,三个词是可能的,但并不漂亮。对于 N 个单词,正则表达式的复杂性增加。请注意,这只是为了好玩(和正则表达式/鬼谷子教育);实际上,我建议遵循其他人所说的:使用树解析库并操纵树。

str = "(ROOT (SQ (NNP Should) (NP (PRP I)) (VP (VB watch) (NP (NP (NNP Game)) (PP (IN of) (NP (NNP Thrones)))) ) (. ?)))"
re = /
  (?<tag>
    [A-Z]+
  ){0}
  (?<word>
    ( g<tag> s
    (?:
      [^()]+ |
      g<word>
    )
    )
  ){0}
  (?<word2>
    g<word> s g<word> |
    ( g<tag> s g<word2> )
  ){0}
  (?<word3>
    g<word> s g<word> s g<word> |
    g<word2> s g<word> |
    g<word> s g<word2> |
    ( g<tag> s g<word3> )
  ){0}
  ( NP s g<word3> )
/x;
puts str[re]
# => (NP (NP (NNP Game)) (PP (IN of) (NP (NNP Thrones))))

除非能够考虑所有可能的结构,否则我看不到使用正则表达式的方法。您所做的适用于简单情况,但正如您发现的那样,它因更深的嵌套结构而失败。我看到两个选项:

  1. 从您在文本中遇到(NP的地方开始,阅读其他字符。保持括号的连续计数。看到(时加,看到)减去。当你达到零时,你已经到达了NP的尽头。

  2. 使用 rubytree 解析树。提取由标签为 NP 的节点主导的所有子树。通过连接叶节点将子树转换回字符串形式。

最新更新