Java 正则表达式匹配拉丁对应字符的变音符号

Java regex matches diacritics for the Latin corresponding characters

我正在尝试使用 [ăâîșțĂÂÎȘȚ] 等正则表达式来匹配罗马尼亚字母变音符号 (ISO 8859-16/Windows-1250)。问题是正则表达式也会与 a、i、s、t、A、I、S、T(上述变音符号对应的拉丁字母字符)的正则表达式匹配,我不想要这个。 由于性能时间的关系,我没有尝试逐个字符地比较字符串。

有没有办法让正则表达式与这些字符完全匹配?

我相信这是因为这些字符被视为两个 Unicode 代码点。我建议尝试使用像 \uFFFF 这样的语法来专门匹配代码点,其中 FFFF 是代码点。确切的语法将取决于您使用的正则表达式实现。

请记住,Unicode 字符可以编码为单个代码点或多个代码点,因此您需要考虑到这一点。示例:à 编码为 U+0061 U+0300 和 U+00E0.

希望对您有所帮助!

如果您的正则表达式以文字呈现的文本形式存在,则它已被合并
并且应该作为不同的代码点存在。

000074    t    LATIN SMALL LETTER T
+
000326    ̦    COMBINING COMMA BELOW
=
00021B    ț    LATIN SMALL LETTER T WITH COMMA BELOW

以防万一,您应该使用十六进制代码点来表示它们,即。 u1B

Java 引擎是否可以从正则表达式中剥离组合字符?
x21B 在哪里变成 x74?可能是这样。

同时,如果您希望源中的字母不会呈现,您可以
使用像 \p{Script=Latin}\p{Block=Combining_Diacritical_Marks}
这样的正则表达式 得到那些。

更新信息:
在四处寻找事实上的解决方案时,我遇到了这个 Java 信息
来自 http://www.regular-expressions.info/unicode.html

In Java, the regex token \uFFFF only matches the specified code point, even when you turned on canonical equivalence. However, the same syntax \uFFFF is also used to insert Unicode characters into literal strings in the Java source code. Pattern.compile("\u00E0") will match both the single-code-point and double-code-point encodings of à, while Pattern.compile("\u00E0") matches only the single-code-point version. Remember that when writing a regex as a Java string literal, backslashes must be escaped. The former Java code compiles the regex à, while the latter compiles \u00E0. Depending on what you're doing, the difference may be significant.

因此,通过在 class 中输入对偶文字,它看起来像 Pattern.compile("[à]")
实际上会匹配

000061    a    LATIN SMALL LETTER A
or
000300    ̀    COMBINING GRAVE ACCENT
or
0000E0    à    LATIN SMALL LETTER A WITH GRAVE  

将代理对放入 classes 中时,这会产生同样的问题。
有一个解决方案。

避免在 class.
中输入这些文字 相反,将它们作为一系列交替
(?:à|_|_|_)

这样做会强制它匹配

000061    a    LATIN SMALL LETTER A
000300    ̀    COMBINING GRAVE ACCENT

0000E0    à    LATIN SMALL LETTER A WITH GRAVE  

它不会匹配 a 独立于 grave 就像你现在看到的那样。

注意 - 如果你只使用“[\\u00E0]”你会错过 a + grave.
这是有效的。

正如 Unicode 中已经提到的那样,有两种选择。

'\u0061'    'a'   LATIN SMALL LETTER A
'\u0300'     ̀     COMBINING GRAVE ACCENT

'\u00E0'    'à'   LATIN SMALL LETTER A WITH GRAVE  

有一个 Normalizer 可以 "normalize" 任何一种形式(并处理连字):

String regex = "(?u)[ăâîșțĂÂÎȘȚ]";
regex = Normalizer.normalize(regex, Form.NFC); // Composed form
Pattern pattern = Pattern.compile(regex);

使用“(?u)”或带有 Pattern.compile 和 UNICODE 标志的标志可能已经解决了问题。但是使用没有单独拉丁语 ('a') 的 Unicode 变体肯定可以。

归一化器尤其适用于搜索到的字符串。