0

我下面的正则表达式应该过滤掉长度为 8-10 的大写单词,其中可能出现 0-2 个数字。它一直适用于我的所有测试,但由于某种原因,它卡在了下面的字符串上。并且n.group(0)只包含一个空字符串而不是匹配的“单词”。

static final Pattern PATTERN = 
    Pattern.compile("\\b(?=[A-Z\\d]{9,10}\\b)(?:[A-Z]*\\d){0,2}[A-Z]*\\b");

Matcher n = LONG_PASSWORD.matcher("foo ID:636152727 bar");

while (n.find()) {
    String s = n.group(0);                  
    resultArrayList.add(s);
}

为什么我的模式匹配ID:636152727

我想过滤掉的一些例子(这是有效的):

  • 啊啊啊啊啊
  • 1啊啊啊啊
  • 1AAAAAAA1

ETC...

4

2 回答 2

2

我没有比 Ωmega 的答案更好的解决方案,但我想我可以解释发生了什么。它归结为第一个\b和最后一个\b匹配相同的位置:就在冒号之后。

这是先行可以匹配的第一个位置,因为它后面跟着九位数字和一个单词边界。然后正则表达式的下一部分尝试匹配两个数字(穿插任意数量的大写字母),然后是单词边界,但失败了。所以它试图只匹配一个数字(同上),然后又失败了。然后它尝试匹配位数字(穿插个字母),它成功了,没有推进匹配位置。该位置仍然是单词边界,因此 final\b也成功。

字边界只是另一个零宽度断言,如前瞻和后瞻。没有理由不能在同一个地方应用两个或多个;您故意使用第一个单词边界和前瞻来做到这一点。如果您将量词应用于断言(如),某些正则表达式风格会将其视为错误\b+,但我认为它们中的任何一个都不会发现这个问题。这是单独的词开始和词尾断言(如 GNU\<\>或 TCL 的\yand \Y)会产生影响的罕见实例之一。

于 2012-11-27T23:41:34.437 回答
1

您需要使用锚点^$»

Pattern.compile("^(?=[A-Z\\d]{9,10}$)(?:[A-Z]*\\d){0,2}[A-Z]*$");

使用此模式:

"(?:^|(?<=\\s))(?=[A-Z\\d]{9,10}(?:\\s|$))(?:[A-Z]*\\d){0,2}[A-Z]*(?=\\s|$)"
于 2012-11-27T21:50:54.017 回答