我已经看了堆栈溢出(替换字符..呃,JavaScript如何不遵循Unicode标准的RegExp等),并没有真正找到一个具体的答案的问题“JavaScript如何匹配重音字符(那些变音符标记)?”

我强迫UI中的一个字段匹配格式:last_name, first_name(最后[逗号空格]第一个),我想提供对变音符的支持,但显然在JavaScript中这比其他语言/平台要困难一些。

这是我最初的版本,直到我想添加变音符支持:

/^[a-zA-Z]+,\s[a-zA-Z]+$/

目前,我正在讨论添加支持的三种方法中的一种,所有这些方法我都已经测试过并且有效(至少在某种程度上,我真的不知道第二种方法的“范围”是什么)。他们是:

显式列出我想接受为有效的所有重音字符(蹩脚和过于复杂):


var accentedCharacters = "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ";
// Build the full regex
var regex = "^[a-zA-Z" + accentedCharacters + "]+,\\s[a-zA-Z" + accentedCharacters + "]+$";
// Create a RegExp from the string version
regexCompiled = new RegExp(regex);
// regexCompiled = /^[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ]+,\s[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ]+$/

这将正确地将姓氏/名字与accentedCharacters中支持的任何重音字符匹配。


我的另一个方法是使用。字符类,有一个更简单的表达式:

var regex = /^.+,\s.+$/;

这将匹配几乎任何东西,至少以:某物,某物的形式。我想还可以……


我刚刚发现的最后一种方法可能更简单……

/^[a-zA-Z\u00C0-\u017F]+,\s[a-zA-Z\u00C0-\u017F]+$/

它匹配了一系列Unicode字符——经过测试并能正常工作,尽管我没有尝试任何疯狂的东西,只是我在我们语言系看到的教员名字的正常内容。


以下是我的担忧:

The first solution is far too limiting, and sloppy and convoluted at that. It would need to be changed if I forgot a character or two, and that's just not very practical. The second solution is better, concise, but it probably matches far more than it actually should. I couldn't find any real documentation on exactly what . matches, just the generalization of "any character except the newline character" (from a table on the MDN). The third solution seems the be the most precise, but are there any gotchas? I'm not very familiar with Unicode, at least in practice, but looking at a code table/continuation of that table, \u00C0-\u017F seems to be pretty solid, at least for my expected input.

老师们提交的表格不会用他们的母语(如阿拉伯语、中文、日语等)写他们的名字,所以我不必担心不符合拉丁字符集的字符


这三种方法中哪一种最适合这项任务?或者有没有更好的解决方案?


当前回答

你可以使用以下方法从字母中移除变音符:

var str = "résumé"
str.normalize('NFD').replace(/[\u0300-\u036f]/g, '') // returns resume

它将删除所有的变音符标记,然后对其执行正则表达式。

参考:

在JavaScript中搜索和排序带有变音符标记的文本

其他回答

来自维基百科:基础拉丁语

对于拉丁字母,我使用

/^[A-zÀ-ÖØ-öø-ÿ]+$/

它避免了连字符和特殊字符。

你可以用这个:

/^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/

重读的拉丁范围\u00C0-\u017F对于我的名字数据库来说不够,所以我将正则表达式扩展为

[a-zA-Z\u00C0-\u024F]
[a-zA-Z\u00C0-\u024F\u1E00-\u1EFF] // includes even more Latin chars

我添加了这些代码块(\u00C0-\u024F同时包含三个相邻的代码块):

\u00C0-\u00FF拉丁语-1补充 \u0100-\u017F拉丁扩展a \u0180-\u024F拉丁扩展b \u1E00-\u1EFF拉丁扩展附加

注意,\u00C0-\u00FF实际上只是Latin-1 Supplement的一部分。它跳过不可打印的控制信号和所有符号,除了放置尴尬的乘× \u00D7和除÷ \u00F7。

[a-zA-Z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u024F] // exclude ×÷

如果你需要更多的编码点,你可以在维基百科的Unicode字符列表中找到更多的范围。例如,您还可以添加Latin Extended-C、D和E,但我省略了它们,因为现在似乎只有历史学家对它们感兴趣,而且D和E集在我的浏览器中甚至不能正确呈现。

原来的正则表达式停止在\u017F上的名称“Șenol”。根据FontSpace的Unicode分析器,第一个字符是\u0218,拉丁大写字母S,下面有逗号。(是的,它通常拼写为cedilla-S \u015E,“Şenol”。但我不会飞到土耳其去告诉他:“你的名字拼错了!”)

XRegExp库有一个名为Unicode的插件,可以帮助解决这类任务。

<script src="xregexp.js"></script>
<script src="addons/unicode/unicode-base.js"></script>
<script>
  var unicodeWord = XRegExp("^\\p{L}+$");

  unicodeWord.test("Русский"); // true
  unicodeWord.test("日本語"); // true
  unicodeWord.test("العربية"); // true
</script>

我的上下文略有不同,仅限于法语:我想通过允许出现口音错误来搜索文本。

例如,我想搜索“maîtrisée”,但要搜索的文本是“…”maitrisee……”。所以,我在JavaScript中使用了正则表达式/ma[I |î|ï]tris[e|é|è|ê|ë]/。

在表达式中,'['和']'定义了一组字符,'|'是一个OR条件。

这个页面给出了一个重音字符的列表:Diacritiques utilisés en français