在下面的POS标记句子(以及类似的句子)中使用正则表达式来捕获只有两个单词的名词名词复合词(即\p{Alnum}+_NN[PS]? \p{Alnum}[PS]?
)并避免捕获作为较大词的一部分的双字匹配短语。
I_PRP will_MD never_RB go_VB to_IN sun_NN devil_NN auto_NN again_RB but_CC my_PRP$ family_NN members_NNS will_MD ._.
我特别希望捕捉family_NN members_NN
但不是sun_NN devil_NN
和devil_NN auto_NN
。
目前我使用以下正则表达式并带有正向前瞻:
"(?=\\b([\\p{Alnum}]+)_(NN[SP]?)\\s([\\p{Alnum}]+)_(NN[SP]?)\\b)."
问题是除了family_NN members_NNS
之外,它还会捕获sun_NN devil_NN
,devil_NN auto_NN
。
答案 0 :(得分:1)
你需要一个前瞻和这里的后视镜。
基本上,对于某些模式P
,您希望当且仅当PP
之前或之后没有P
时,(?<!P)PP(?!P)
才会匹配。
粗略的方式,前瞻和后视操作员:
(?<!...)
(?!...)
和...
分别是正则表达式中的负向前瞻和负前瞻锚,其中P
代表正则表达式。
如果我们将[\p{AlNum}]+_NN[PS]?
作为:
private static final String P = "[\\p{AlNum}]+_NN[PS]?";
private static final String RE = "(?<!" + P + ")"
+ "\\s+(" + P + "\\s+" + P + ")\\s+(?!" + P + ")";
private static final Pattern PATTERN = Pattern.compile(RE);
并考虑空格,然后一个解决方案的草图,允许每个标记之间的空格,看起来像:
reflect
然而,这只是一幅草图。
鉴于输入的复杂性,您可能想要做更多,所以不确定正则表达式是否是您最终寻找的工具。