【问题标题】:Stripping characters using a regex fails using literal characters with diacritics, apostrophes, accents, and the like使用带有变音符号、撇号、重音符号等的文字字符,使用正则表达式剥离字符失败
【发布时间】:2017-12-24 16:12:48
【问题描述】:

我正在尝试生成一个符合 XSD 中模式的字符串。为了去除 XSD 模式中没有出现的任何字符,我正在执行以下操作(从我的代码中复制的 replaceAll 调用):

import java.lang.String;

public class HelloWorld {
    public static void main(String[] args) {
        test("Führ");
    }

    private static void test( String name ) {
        name = name.toUpperCase( );
        name = name.replaceAll (
            "[^A-ZА-ЯΑ-ΩÄÀÁÂÃÅǍĄĂÆÇĆĈČĎĐÐÈÉÊËĚĘĜĢĞĤÌÍÎÏĴĶĹĻŁĽÑŃŇÖÒÓÔÕŐØŒŔŘẞŚŜŞŠȘŤŢÞȚÜÙÚÛŰŨŲŮŴÝŸŶŹŽŻ, '\\-–]", 
            ""
        );
        System.out.println(name);
    }
}

此片段运行良好,并打印出“FÜHR”。但是,在我正在运行的环境中,使用完全相同的replaceAll 语句,replaceAll 调用删除了Ü 字符并打印出FHR,其中包含来自数据库并开始的数据(即名称)与代码 sn-p ("Führ") 中的字符相同。

我很困惑...可能是什么原因,我该如何解决这个问题?


PS:源文件编码为UTF-8(Eclipse .settings:encoding//<<<src-path>>>.java=UTF-8

【问题讨论】:

  • 尝试设置 LC_ALL=C。
  • @WiktorStribiżew 这看起来是一个 Unix 设置...我会尝试为 Windoze 环境找到一个等价物。
  • @WiktorStribiżew 尝试使用 Locale.setDefault( Locale.ROOT );... 没有变化。
  • 什么是"在我运行的环境中"详细?
  • 我认为正则表达式是错误的,因为我只匹配特定的代码点,而不是组合的字符 (U + ¨)。

标签: java regex unicode character-encoding replaceall


【解决方案1】:

显然,当匹配带有变音符号、撇号、重音符号等的字符时,应该使用 unicode 单代码点来指定字符。

例如,对于 à 字符,正则表达式应指定 \u00E0 而不是文字 à。原因是 à 字符可以通过两种方式编码:

  • 作为单个代码点的 à 字符(文字 à)
  • 作为双码点的 à 字符(a 后跟重音 `)

在正则表达式中指定 unicode 代码点 \u00E0 将匹配 à 的两种编码。在正则表达式中指定文字 à 只会匹配该字符在代码片段中的编码方式,如果它被编码为双码点,它将不匹配相同的单码点版本字符。

使用 unicode 单码点重写正则表达式解决了这个问题。对于问题中的 Ü 字符,正则表达式应指定 \u00DC。这匹配 Ü 的单码点和双码点编码。

我在这里找到了导致解决方案的信息:Regex Tutorial - Unicode Characters and Properties(段落:匹配特定代码点)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 2016-05-24
    • 2014-03-27
    • 1970-01-01
    • 2011-11-20
    • 2015-10-29
    相关资源
    最近更新 更多