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

时间:2017-02-13 21:22:19

标签: java regex nlp diacritics

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

无论如何,我是否可以使正则表达式与这些字符完全匹配?

3 个答案:

答案 0 :(得分:2)

如果你的正则表达式作为文字渲染文本存在,它已经被合并了 并且应该作为不同的代码点存在。

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

只是,你应该使用十六进制代码点来代表它们,即。 u\021B

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

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

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

  

在Java中,正则表达式标记\ uFFFF仅匹配指定的标记       代码点,即使你打开规范等价。       但是,同样的语法\ uFFFF也用于插入       Unicode字符到Java源代码中的文字字符串       码。 Pattern.compile(“\ u00E0”)将匹配       à的单码点和双码点编码,       而Pattern.compile(“\ u00E0”)仅匹配       单码点版本。记得写的时候       正则表达式作为Java字符串文字,必须转义反斜杠。       前Java代码编译正则表达式à,而后者       编译\ u00E0。取决于你正在做什么,       差异可能很大。

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

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

在将代理对放入课堂时,这也存在同样的问题 有一个解决方案。

避免在课堂内输入这些文字 相反,把它们作为一系列的替代品 (?:à|_|_|_)

这样做会强制它匹配

000061    a    LATIN SMALL LETTER A
000300    ̀    COMBINING GRAVE ACCENT

0000E0    à    LATIN SMALL LETTER A WITH GRAVE  

与您现在看到的 grave 无法匹配a

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

答案 1 :(得分:0)

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

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

我希望这有帮助!

答案 2 :(得分:0)

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

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

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

有一个Normalizer可以“规范化”为任何一种形式(并处理连字):

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

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

规范化器尤其应应用于搜索到的字符串。