我已经看了堆栈溢出(替换字符..呃,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.

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


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


当前回答

/^[\pL\pM\p{Zs}.-]+$/u

解释:

\pL -匹配任何语言的任何类型的字母 \pM -匹配一个打算与另一个字符组合的字符(例如重音,变音,围框等) \p{Zs} -匹配一个不可见的空白字符,但确实占用空间 u -模式和主题字符串被视为UTF-8

与其他提议的正则表达式(如[A-Za-zÀ-ÖØ-öø-])不同,这将适用于所有特定于语言的字符,例如Šš被此规则匹配,但不被此页上的其他规则匹配。

不幸的是,JavaScript本身并不支持这些类。但是,您可以使用xregexp,例如:

const XRegExp = require('xregexp');

const isInputRealHumanName = (input: string): boolean => {
  return XRegExp('^[\\pL\\pM-]+ [\\pL\\pM-]+$', 'u').test(input);
};

其他回答

这三种方法中哪一种最适合这项任务?

要精确匹配所有拉丁字符及其重音版本,Unicode范围可能提供了最佳解决方案。它们可以扩展到所有非空白字符,这可以使用\S字符类来实现。

我强迫一个字段在一个UI匹配的格式:last_name, first_name(最后[逗号空格]第一)

我在这里看到的最基本的问题不是变音符,而是空格。有一些名称由多个单词组成,例如标题。所以你应该使用最通用的,那就是允许所有的东西,但逗号区分姓和名:

/[^,]+,\s[^,]+/

但是你的第二个解决方案。字符类也很好,你可能只需要关心多个逗号。

接受所有口音更简单的方法是:

[A-zÀ-ú] // accepts lowercase and uppercase characters
[A-zÀ-ÿ] // as above, but including letters with an umlaut (includes [ ] ^ \ × ÷)
[A-Za-zÀ-ÿ] // as above but not including [ ] ^ \
[A-Za-zÀ-ÖØ-öø-ÿ] // as above, but not including [ ] ^ \ × ÷

有关按数字顺序列出的字符,请参阅Unicode字符表。

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

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

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

参考:

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

你可以用这个:

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

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

对于拉丁字母,我使用

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

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