JavaScript正则表达式+Unicode重音组合字符

5

我希望能够在非洲约鲁巴语中匹配到这个字符 'ẹ́'。通常,这是由一个带有 '\u0323' 下方点的变音符号 'é' 组合而成的。我发现:

'é\u0323'.match(/[é]\u0323/) works but
'ẹ́'.match(/[é]\u0323/) does not work.

我不只是想匹配'e',我想匹配所有的组合。目前,我的解决方案涉及枚举所有可能的组合,像这样:/[ÁÀĀÉÈĒẸE̩Ẹ́É̩Ẹ̀È̩Ẹ̄Ē̩ÍÌĪÓÒŌỌO̩Ọ́Ó̩Ọ̀Ò̩Ọ̄Ō̩ÚÙŪṢS̩áàāéèēẹe̩ẹ́é̩ẹ̀è̩ẹ̄ē̩íìīóòōọo̩ọ́ó̩ọ̀ò̩ọ̄ō̩úùūṣs̩]/
有没有更简洁、更好的方法来实现这一点呢?或者 JavaScript 中正则表达式匹配 Unicode 音标字符组合不能这么容易吗?
谢谢。

如果我必须诚实地说,我宁愿阅读和维护那个短的字符串,而不是解密和理解可能更聪明的正则表达式中的\uxxxx部分。使用查找表始终比先计算字符更快。如果正则表达式失败,一个可能的方法是将字符渲染在一个span中,然后进行比较。 - mplungjan
这是一个好观点。也许现在的方法更好。 - user2530580
我最终选择了\uxxxx部分,因为在vim中进行编辑时,当存在不同流方向的变宽Unicode点并以相当奇妙的方式影响光标位置时,这样做更有意义:光标位置基本上变成了随机变量。 - user2530580
2个回答

6
通常的解决方法是使用Unicode属性和/或脚本, 但JavaScript不支持它们。但有一个名为XRegExp的库可以添加此支持。使用此库,您可以使用以下内容:\p{L}:匹配任何语言的任何字母。\p{M}:用于与另一个字符组合的字符(例如重音符号、umlauts、包围框等)。因此,您的字符类将如下所示:
[\p{L}\p{M}]+

如果要匹配Unicode表中的所有可能字母,您可以使用以下代码:\p{L}

如果您想限制匹配范围,您可以查看Unicode脚本,并将\p{L}替换为脚本,它们会收集某些语言的所有字母。例如,\p{Latin}表示所有拉丁字母或\p{Cyrillic}表示所有西里尔字母。


自从Edge 13和Node 8.6以来,u标志在所有流行的浏览器中都可以使用。 - undefined

4
通常这是通过将“é”与带有下方点的“\u0323”组合而成。
然而,这不是你在这里看到的。
'ẹ́'

那不是U+0065,U+0323,而是U+1EB9,U+0301——将与锐音变音符组合在一起。

通常的解决方案是在比较之前对每个字符串进行规范化(通常是Unicode正规式C)。

我不仅想匹配e。我想匹配所有的组合。

通常情况下,没有变音符号的匹配是通过规范化为正规式D并删除所有组合变音符号来完成的。

不幸的是,在JS中没有规范化,因此如果您需要它,您必须拖入代码来执行它,其中必须包括大量的Unicode数据表。这样的努力是unorm。要基于Unicode属性(如组合变音符号)挑选字符,您还需要具有对Unicode数据库支持的regexp引擎,例如XRegExp Unicode Categories

服务器端语言(例如Python、.NET)通常具有本地支持Unicode规范化,因此如果可以在服务器上处理,那么通常会更容易。


这解释清楚了。谢谢。 - user2530580
Bobince,如果你有时间的话,可以更新一下,让它引用ES6的.normalize - Sergio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接