【问题标题】:How to avoid capturing overlapping patterns while using java regex?使用 java regex 时如何避免捕获重叠模式?
【发布时间】:2016-03-31 15:01:17
【问题描述】:

在以下带有 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_NNdevil_NN auto_NN

目前,我使用以下正则表达式和积极的前瞻:

"(?=\\b([\\p{Alnum}]+)_(NN[SP]?)\\s([\\p{Alnum}]+)_(NN[SP]?)\\b)."

除了family_NN members_NNS 之外,问题还在于它捕获了sun_NN devil_NNdevil_NN auto_NN

【问题讨论】:

标签: java regex


【解决方案1】:

你需要一个前瞻一个前瞻。

基本上,对于某些模式P,当且仅当它之前或之后没有P 时,匹配PP

粗略的方式,使用前瞻和后向运算符:

(?<!P)PP(?!P)

(?&lt;!...)(?!...) 分别是正则表达式中的负后向和负前瞻锚,其中... 代表正则表达式。

如果我们将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);

这只是一个草图。

鉴于输入的复杂性,您可能想要做更多,因此不确定正则表达式最终是否是您真正要寻找的工具。

【讨论】:

  • 然而,Java 不允许 + 量词后视(可变长度),但允许有限重复,例如 (?&lt;!\s\p{Alnum}{1,20}_NN[SP]?\s),如果这足够的话。
  • @fge 感谢您的回复。如果 PP 在句首还是句尾呢?
  • @bobblebubble 你确定因为+ 似乎在我在我的问题中提到的正则表达式中工作。
  • @Meghi Afaik +*lookbehind in Java regex 中不起作用。
  • @fge RE 不会捕获出现在句子开头或结尾的 PP,因为 \\s+。我试图通过将\\s+ 更改为\\s* 来解决此问题,但是当我这样做时,sun_NN devil_NN 被捕获。我该如何解决这个问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 2021-06-07
  • 2022-12-05
相关资源
最近更新 更多