Java 21 与 Java 17 模式匹配器

Java 21 vs Java 17 pattern matcher

提问人:SteVio 提问时间:11/17/2023 最后编辑:SteVio 更新时间:11/18/2023 访问量:84

问:

我目前正在尝试使用 Java 21 运行一个项目,该项目目前使用 Java17 运行没有任何问题。

对于我们的一些正则表达式模式,有些与 Java21 的匹配在 Java17 中不匹配,反之亦然。

它可以使用以下模拟代码重现:

public static void main(String[] args) {
        //english
        test(
                "...their sample variance, and σ2N their population variance.",
                "(?<![A-Z\\$€£¥฿฿=]-?[0-9\\.]{0,5})((\\b|\\-)[0-9]{1,5}[0-9,.]{0,5}(€|¥|฿|฿|°C|°F|°De?|°R[éeøa]?|(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|f|z|y)[ΩΩm]|[ΩΩ]|(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)?N|[kKMGTPEZY]i?B|[kmµnp]g|[Mk]t|kWh|GWa|MWd|MWh)(?!\\w))",
                true,
                null);
        //french
        test(
                "Il a été mis au banc de la société.",
                "\\bau (banc) (?:des nations|de la (?:société|ville|communauté|France)|de l['´‘’′](?:Europe|empire|église|islam))\\b",
                false,
                "au banc de la société");
    }

    private static void test(String text, String regex, boolean caseSensitive, String expected) {
        int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
        Pattern pattern = Pattern.compile(regex, flags);
        Matcher matcher = pattern.matcher(text);
        int start = 0;
        String match = null;
        while (matcher.find(start)) {
            match = text.substring(matcher.start(), matcher.end());
            start = matcher.end();
        }
        System.out.println("Expected: " + expected);
        System.out.println("Got: " + match);
    }

Java 17 的输出:

Expected: null
Got: null
Expected: au banc de la société
Got: au banc de la société

Java 21 的输出:

Expected: null
Got: 2N
Expected: au banc de la société
Got: null

在 Java 21 中,预期与 Java 17 中的行为相同。

正则表达式 java-17 java-21

评论

4赞 rzwitserloot 11/18/2023
您在源文件中使用了非 ASCII。第 1 步是确保编码问题不是罪魁祸首。三重检查您的源文件是否保存为 UTF_8(这是编辑器中的设置),以及您是否正在使用 - 或告诉 maven 或您用来执行此操作的任何东西进行编译。编辑器和调用之间字符集编码对齐失败可能会导致这种情况,因此,检查很重要。编辑问题,并反映您已经将其作为解释删除了。javac -encoding UTF-8 *.javajavac
4赞 rzwitserloot 11/18/2023
另请注意,您的粘贴是错误的。这不可能导致您显示的输出 - 您的输出以:“Expected:”开头,但您的代码传递了空字符串。因此,你粘贴的不是你运行的。也要更新它。事情是这样的:你要求一些非常奇怪的东西,或多或少是 API 中烘焙的错误。1000 个案例中有 999 个是试点错误。null
3赞 user85421 11/18/2023
也许“正则表达式字符类现在默认仅匹配 ASCII 字符 (JDK-8264160)”;不太可能的“支持 Unicode 14.0 (JDK-8268081)”(均来自发行说明 Java 19);或“支持 Unicode 15.0 (JDK-8284842)”(发行说明 Java 20)\b
1赞 rzwitserloot 11/18/2023
这将完全解释这一点,user85421。将该评论升级为答案,我认为:)
1赞 Holger 11/18/2023
旁注:您不需要维护变量。只需用于从上一场比赛的末尾(或第一次通话的开始)开始搜索。此外,可以简化为 .Just This 将记录最后的匹配项,就像您的代码一样。startmatcher.find()text.substring(matcher.start(), matcher.end())matcher.group()while(matcher.find()) match = matcher.group();

答:

-1赞 SteVio 11/20/2023 #1

也许“正则表达式 \b 字符类现在默认仅匹配 ASCII 字符 (JDK-8264160)”;不太可能的“支持 Unicode 14.0 (JDK-8268081)”(均来自发行说明 Java 19);或“支持 Unicode 15.0 (JDK-8284842)”(发行说明 Java 20)– user85421 2数天之前

评论

0赞 hc_dev 11/20/2023
请注意格式化(使用代码格式化)。如果您引用并使用引号格式,请同时提及来源。