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

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


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


当前回答

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

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

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

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

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

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

其他回答

重读的拉丁范围\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>

你可以用这个:

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

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

[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字符表。

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

对于拉丁字母,我使用

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

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