gpt4 book ai didi

java - 正则表达式\p{Cs} 与 Java 16 中的符号不​​匹配

转载 作者:行者123 更新时间:2023-12-04 12:04:42 24 4
gpt4 key购买 nike

有谁知道为什么正则表达式 \p{Cs}与符号不匹配 񡠼在 Java 16 中?
它曾经在 Java 11 中匹配它。
java 11

jshell 
| Welcome to JShell -- Version 11.0.7
| For an introduction type: /help intro

jshell> import java.util.regex.*

jshell> var text = new StringBuilder().appendCodePoint(55622).appendCodePoint(56380)
text ==> 񡠼

jshell> Pattern.compile("\\p{Cs}").matcher(text).find()
$3 ==> true
java 16
INFO: Created user preferences directory.
| Welcome to JShell -- Version 16.0.1
| For an introduction type: /help intro

jshell> import java.util.regex.*

jshell> var text = new StringBuilder().appendCodePoint(55622).appendCodePoint(56380)
text ==> 񡠼

jshell> Pattern.compile("\\p{Cs}").matcher(text).find()
$3 ==> false

最佳答案

首先,您的“符号񡠼 ”的代码点为 399420,Unicode 标准尚未分配该代码点(尚未分配),因此,如果您在此处看到有用的信息,则这是您系统的非标准行为。
您构造字符串的方式在语义上是不正确的,但恰好创建了预期的字符串。由于历史原因,Java 的 API 以 UTF-16 表示为中心。
当您使用两个代理字符定义符号时,即

var text = "\uD946\uDC3C";
System.out.println(text.codePointAt(0));
你会得到
399420
另一方面,当您使用
var text = new StringBuilder().appendCodePoint(399420);
text.chars().forEach(c -> System.out.printf("\\u%04X", c));
System.out.println();
你会得到
\uD946\uDC3C
也就是说,两个代理的序列UTF-16 char单位 \uD946 , \uDC3C相当于单个代码点 399420 .从概念上讲,字符串由单个代码点组成,换句话说,
System.out.println(text.codePointCount(0, text.length()) + " codepoint(s)");
System.out.println(text.codePointAt(0));
System.out.println("type " + Character.getType(text.codePointAt(0)));
将打印
1 codepoint(s)
399420
type 0
在任一情况下。型号 0表示此代码点未分配。
您正在使用 appendCodePoint用于将两个 UTF-16 单元附加到 StringBuilder ,但由于此方法处理 BMP 的代码点与 UTF-16 单元的方式相同,它也恰好构造了相同的字符串。
由于代码点的类别是“未分配”,所以不应该是“代理”,所以 \p{Cs}永远不应该在这里找到匹配项。当处理一个有效的 Unicode 字符串时,你永远不应该遇到这个类别,因为它只能匹配不能被解释为 BMP 之外的代码点的悬空代理字符。 .
但是存在错误 JDK-8247546, Pattern matching does not skip correctly over supplementary characters .在 Java 16 之前,正则表达式引擎确实正确处理了位置 0 处的代码点,但仅前进了一个 char位置,所以在查看 char 时发现了一个悬空的代理字符职位 1独自的。
我们可以使用
var m = Pattern.compile("\\p{Cs}").matcher(text);
if(m.find()) {
System.out.println("found a match at " + m.start());
}
在 JDK 16 之前打印“found a match at 1”,这是错误的,位置 1char 处有单个代码点时应该跳过职位 01 .
此错误已在 JDK 16 中修复。因此,现在该字符串被视为“未分配”类别的单个代码点。当然,这个类别在 future 可能会再次发生变化。但它永远不应该是“代理”。

关于java - 正则表达式\p{Cs} 与 Java 16 中的符号不​​匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68226103/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com