regex 如何在Java中检测字符串是否包含西里尔字母?

ffx8fchx  于 2023-08-08  发布在  Java
关注(0)|答案(3)|浏览(97)

我想检测字符串是否包含西里尔字母。
在PHP中,我做了这样的事情:

preg_match('/\p{Cyrillic}+/ui', $text)

字符串
在Java中有什么是一样的?

siv3szwd

siv3szwd1#

请尝试以下操作:

Pattern.matches(".*\\p{InCyrillic}.*", text)

字符串
你也可以避免使用正则表达式,而使用类Character.UnicodeBlock

for(int i = 0; i < text.length(); i++) {
    if(Character.UnicodeBlock.of(text.charAt(i)).equals(Character.UnicodeBlock.CYRILLIC)) {
        // contains Cyrillic
    }
}

7dl7o3gd

7dl7o3gd2#

下面是另一种在java 8中处理流的方法:

text.chars()
        .mapToObj(Character.UnicodeBlock::of)
        .filter(Character.UnicodeBlock.CYRILLIC::equals)
        .findAny()
        .ifPresent(character -> ));

字符串
或者另一种方式,保持索引:

char[] textChars = text.toCharArray();
IntStream.range(0, textChars.length)
                 .filter(index -> Character.UnicodeBlock.of(textChars[index])
                                .equals(Character.UnicodeBlock.CYRILLIC))
                 .findAny() // can use findFirst()
                 .ifPresent(index -> );

  • 请注意:* 我在这里使用char数组而不是String,因为通过索引获取元素的性能优势。
wwtsj6pe

wwtsj6pe3#

上面使用UnicodeBlock的例子可以很好地工作,但如果你喜欢,也可以使用Character.UnicodeScriptenum

boolean containsCyrillic = "Your String Goes Here".codePoints()
    .mapToObj(Character.UnicodeScript::of)
    .anyMatch(Character.UnicodeScript.CYRILLIC::equals);

字符串
如果你不信任你的输入,你可以使用Character.isValidCodePoint来提高防御性:

boolean containsCyrillic =
    "Your Untrusted String Goes Here".codePoints()
        .filter(Character::isValidCodePoint)
        .mapToObj(Character.UnicodeScript::of)
        .anyMatch(s -> s == Character.UnicodeScript.CYRILLIC);


如果你有兴趣分析文本中的各种脚本,例如确定文本的主要脚本,你可以跟踪各种脚本中的代码点数量:

Map<Character.UnicodeScript,Long> scripts = 
    "Your Untrusted String Goes Here".codePoints()
        .filter(Character::isValidCodePoint)
        .mapToObj(Character.UnicodeScript::of)
        .collect(groupingBy(
            Function.identity(),
            counting()));


我们也可以更高效地使用EnumMap,因为Character.UnicodeScriptenum

Map<Character.UnicodeScript,Long> scripts = 
    "Your Untrusted String Goes Here".codePoints()
        .filter(Character::isValidCodePoint)
        .mapToObj(Character.UnicodeScript::of)
        .collect(groupingBy(
            Function.identity(),
            () -> new EnumMap<>(Character.UnicodeScript.class),
            counting()));


如果你只是对多数票感兴趣,那么你可以试试这个:

Optional<Character.UnicodeScript> predominantScript = 
    "Your Untrusted String Goes Here".codePoints()
        .filter(Character::isValidCodePoint)
        .mapToObj(Character.UnicodeScript::of)
        .filter(s -> s != Character.UnicodeScript.COMMON
            && s != Character.UnicodeScript.INHERITED
            && s != Character.UnicodeScript.UNKNOWN)
        .collect(groupingBy(
            Function.identity(),
            () -> new EnumMap<>(Character.UnicodeScript.class),
            counting()))
        .entrySet()
        .stream()
        .sorted(
            Comparator
            .<Map.Entry<Character.UnicodeScript, Long>>comparingLong(Map.Entry::getValue)
            .reversed()
            .thenComparing(Map.Entry::getKey))
        .map(Map.Entry::getKey)
        .findFirst();


我们过滤掉Character.UnicodeScript.COMMONCharacter.UnicodeScript.INHERITEDCharacter.UnicodeScript.UNKNOWN,因为它们是用于共享代码点的“捕获所有”类别,Map到所有代码点,或者只是无法识别的代码点(根据规范),而不是单独的脚本。

相关问题