模式: 如何从字符类中减去匹配的字符?

5

在字符类中,是否有可能减去一个匹配的字符?

Java文档有关于字符类减法的示例:

[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个回答

3

使用

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

你的字符将分成组13

这是通过使用负向前瞻来实现的,确保第一个字符组中第二个字符后面的字符是不同的字符。


1

试试这个

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

(?!\\1) 是一个 负向先行断言,它确保 \\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 ==> 成功


1
你在使用错误的工具来完成任务。可以使用正则表达式来检测字符对,但是你只需要使用 != 来测试字符对中的字符是否相同即可。认真地说,没有必要在正则表达式中做所有的事情——这会导致代码难以阅读、不可移植,并且除了“看起来很酷”外毫无益处。

@Kilian:这种模式只是许多模式之一(还有很多简单的模式)用于匹配字符串部分 - 所以这不仅仅是为了“酷”,正如你所说 - 系统迭代模式并匹配它们... 如果我按照你建议的方式去做 - 我会得到更“不酷”的解决方案,因为我需要为一个或另一个情况添加自定义ifs... - Laimoncijus
@flesk:非常好,我给你点赞! :) - Laimoncijus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接