我试图从斯坦福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))))
答案 0 :(得分:2)
特别是对于三个单词,它是可能的,但不是很漂亮。对于N个单词,正则表达式的复杂性上升。请注意,这只是为了好玩(和regexp / Oniguruma教育);实际上,我建议跟其他人说的一样:使用树解析库并操纵树。
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 :(得分:0)
我没有看到使用正则表达式的方法,除非能够考虑所有可能的结构。你做了什么适用于简单的情况,但正如你所发现的那样,它失败了更深层的嵌套结构。我看到两个选择:
从文本中遇到(NP
的位置开始,请阅读其他字符。保持括号的运行记录。当您看到(
时添加到它,当您看到)
时减去。当你达到零时,你已经到了NP
的末尾。
使用rubytree解析树。提取由标签为NP
的节点支配的所有子树。通过连接叶节点将子树转换回字符串形式。