2012-02-07 53 views
5

是否可以减去字符类中的匹配字符?模式:如何减少字符类中的匹配字符?

Java docs都具有约字符类的例子与减法:

[a-z&&[^bc]] - a through z, except for b and c: [ad-z] (subtraction) 
[a-z&&[^m-p]] - a through z, and not m through p: [a-lq-z](subtraction) 

我想要写图案,该图案匹配两个双字字符,当对不是相同的:

1) "aaaa123" - should NOT match 
2) "aabb123" - should match "aabb" part 
3) "aa--123" - should NOT match 

我用以下模式接近成功:

([\w])\1([\w])\2 

,但当然它不适用于情况1,所以我需要减去第一组的匹配。但是,当我尝试这样做:

Pattern p = Pattern.compile("([\\w])\\1([\\w&&[^\\1]])\\2"); 

我得到一个异常:

Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence near index 17 
([\w])\1([\w&&[^\1]])\2 
       ^
    at java.util.regex.Pattern.error(Pattern.java:1713) 

如此看来它不与团体工作,但只是列出具体的字符。以下模式编译没有问题:

Pattern p = Pattern.compile("([\\w])\\1([\\w&&[^a]])\\2"); 

是否有任何其他方式来编写此类模式?

回答

3

使用

Pattern p = Pattern.compile("((\\w)\\2(?!\\2))((\\w)\\4)"); 

你的角色会进入组13

这可以通过使用负向预测来确保第一个字符组中第二个字符后面的字符是不同的字符。

1

您正在使用错误的工具进行工作。尽一切办法使用正则表达式来检测字符对对,但您可以使用!=来测试对中的字符是否相同。严重的是,没有理由在正则表达式中使用的所有内容 - 它会导致无法读取,不可移植的代码,并且除了“看起来很酷”之外,没有其他好处。

+1

正则表达式确实让一个看起来很酷:HTTP:// XKCD。com @ 208 @ – flesk 2012-02-07 10:03:15

+0

@Kilian:这个模式只是用于匹配字符串部分的许多(也有很多简单的)模式之一 - 所以这不仅仅是因为你说的“酷” - 系统遍历模式并匹配它们。 ..如果我会用你建议的方式去 - 我会让它更“不冷酷”的解决方案,因为我需要为一个或另一个案例添加自定义的'ifs' ... – Laimoncijus 2012-02-07 10:03:34

+0

@flesk:非常好,从我+1 ! :) – Laimoncijus 2012-02-07 10:04:38

1

尝试此

String regex = "(\\w)\\1(?!\\1)(\\w)\\2"; 
Pattern pattern = Pattern.compile(regex); 

(?!\\1)negative lookahead,它确保的\\1内容不被以下

我的测试码

String s1 = "aaaa123"; 
String s2 = "aabb123"; 
String s3 = "aa--123"; 
String s4 = "123ccdd"; 

String[] s = { s1, s2, s3, s4 }; 
String regex = "(\\w)\\1(?!\\1)(\\w)\\2"; 

for(String a : s) { 
    Pattern pattern = Pattern.compile(regex); 
    Matcher matcher = pattern.matcher(a); 

    if (matcher.find()) 
     System.out.println(a + " ==> Success"); 
    else 
     System.out.println(a + " ==> Failure"); 
} 

输出

aaaa123 ==>未能
aabb123 ==>成功
AA - 123 ==>未能
123ccdd ==>成功