regex 正则表达式:只匹配字符串中不同的字符

5gfr0r5j  于 2022-11-18  发布在  其他
关注(0)|答案(2)|浏览(213)

有一个关于Java中正则表达式匹配的问题。给定了一个定义长度的字符串。现在我想用一个匹配器来检查这个字符串中包含的每个字符是否都不同。
例如(仅限长度为8的通道):

String a = "abcdefgz" -> pass
String b = "aacdefgz" -> fail
String c = "abcdefghz" -> fail

因此,匹配长度将简单地为:

"^[a-zA-Z]{8}$"

但是要让它在每个包含的char都必须是唯一的条件下工作是相当坚韧的。

9lowa7mx

9lowa7mx1#

这个匹配包含重复项的字符串。这基本上是你要找的内容的反向

.*(.)+.*\1.*

如果合适的话,你可以选择与这个表达式 * 不匹配 * 的字符串。或者检查regex negative match来改进它。

bq9c1y66

bq9c1y662#

我有一个非常丑陋的方式来做这个使用regex。
它使用已命名的捕获组(?<name>)、反向引用\k<name>和负前瞻Assert(?!)

@Test
public void testForNonRepeatedCharactersUsingRegex() {
    Pattern p = Pattern.compile("^(?<c1>[a-zA-Z])(?!.*\\k<c1>)" +
            "(?<c3>[a-zA-Z])(?!.*\\k<c3>)" +
            "(?<c2>[a-zA-Z])(?!.*\\k<c2>)" +
            "(?<c4>[a-zA-Z])(?!.*\\k<c4>)" +
            "(?<c5>[a-zA-Z])(?!.*\\k<c5>)" +
            "(?<c6>[a-zA-Z])(?!.*\\k<c6>)" +
            "(?<c7>[a-zA-Z])(?!.*\\k<c7>)" +
            ".$");
    Assertions.assertTrue(p.matcher("abcdefgh").matches());
    Assertions.assertTrue(p.matcher("ABCDEFGH").matches());
    Assertions.assertFalse(p.matcher("12345678").matches());
    Assertions.assertFalse(p.matcher("abefgh").matches());
    Assertions.assertFalse(p.matcher("").matches());
    Assertions.assertFalse(p.matcher("abcdefga").matches());
    Assertions.assertFalse(p.matcher("aaaabbbb").matches());
}

如果您可以不使用regex,那么一个更干净、更清晰的解决方案是:

@Test
public void testForNonRepeatedCharactersUsingStreams() {
    Assertions.assertTrue(uniqueCharacterSequence("abcdefgh", 8));
    Assertions.assertTrue(uniqueCharacterSequence("ABCDEFGH", 8));
    Assertions.assertFalse(uniqueCharacterSequence("12345678", 8));
    Assertions.assertFalse(uniqueCharacterSequence("abefgh", 8));
    Assertions.assertFalse(uniqueCharacterSequence("", 8));
    Assertions.assertFalse(uniqueCharacterSequence("abcdefga", 8));
    Assertions.assertFalse(uniqueCharacterSequence("aaaabbbb", 8));
}

private static boolean uniqueCharacterSequence(String s, int length) {
    return  s.length() == length &&
            s.codePoints().allMatch(Character::isLetter) &&
            s.codePoints().distinct().count() == length;
}

相关问题