1
public static void main(String[] args) {

        Pattern compile = Pattern
                .compile("[0-9]{1,}[A-Za-z]{1,}|[A-Za-z][0-9]{1,}|[a-zA-Z][a-zA-Z0-9\\.\\-_/#]{2,}|[0-9]{3,}[A-Za-z][a-zA-Z0-9\\.\\-_/#]*|[0-9][0-9\\-]{4,}|[0-9][0-9\\-]{3,}[a-zA-Z0-9\\.\\-_/#]+");
        Matcher matcher = compile.matcher("i5-2450M");
        matcher.find();
        System.out.println(matcher.group(0));
    }

我认为这应该返回i5-2450M,但i5实际上返回

4

1 回答 1

4

问题是使用了匹配的第一个交替。

在这种情况下,第二个交替([A-Za-z][0-9]{1,}匹配i5)“阴影”任何后续交替。

// doesn't match
[0-9]{1,}[A-Za-z]{1,}|
// matches "i5"
[A-Za-z][0-9]{1,}|
// the following are never even checked, because of the previous match
[a-zA-Z][a-zA-Z0-9\\.\\-_/#]{2,}|
[0-9]{3,}[A-Za-z][a-zA-Z0-9\\.\\-_/#]*|
[0-9][0-9\\-]{4,}|
[0-9][0-9\\-]{3,}[a-zA-Z0-9\\.\\-_/#]

(请注意,帖子中的正则表达式可能存在严重问题——例如,0---#将与最后一条规则匹配——应该解决,但由于不是交替行为。)

要解决此问题,请先安排最具体的交替。在这种情况下,它将把第二个交替放在其他交替条目的下方。(还要查看其他的替换和交互;也许整个正则表达式可以简化?)

使用简单的单词边界 ( \b) 在这里不起作用,因为-它被视为非单词字符。但是,根据正则表达式的含义,锚点 ($^) 可以用于交替:例如^existing_regex$. 这不会改变交替的行为,但导致回溯初始匹配i5,从而导致考虑后续的交替条目,因为无法在交替之后立即匹配输入结束团体。


来自Java 正则表达式交替运算符“|” 行为似乎坏了

Java 使用 NFA 或正则表达式导向风格,如 Perl、.NET、JavaScript 等,与 sed、grep 或 awk 不同。一旦其中一个备选方案匹配,预计将退出,而不是坚持最长的匹配。

(此问题中接受的答案使用单词边界。)

模式

Pattern 引擎使用Perl 5 中的有序交替执行传统的基于 NFA 的匹配。

于 2012-08-21T04:49:00.730 回答