重音字符(变音符号)的具体 Javascript 正则表达式

IT技术 javascript regex unicode
2021-01-19 14:00:03

我查看了 Stack Overflow(替换字符.. ehJavaScript 如何不遵循有关 RegExp 的 Unicode 标准等)并且还没有真正找到这个问题的具体答案:

How can JavaScript match for accented characters (those with diacritical marks)?

我正在强制 UI 中的字段匹配格式: last_name, first_name (last [comma space] first),并且我想提供对变音符号的支持,但显然在 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.+$/;
  • 这几乎可以匹配任何东西,至少在以下形式中:something, something没关系,我想...

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

/^[a-zA-Z\u00C0-\u017F]+,\s[a-zA-Z\u00C0-\u017F]+$/
  • 它匹配一系列 unicode 字符 - 测试和工作,虽然我没有尝试任何疯狂的东西,只是我在我们的语言部门看到的教员姓名的正常内容。

以下是我的担忧:

  1. 第一个解决方案太局限了,而且草率和令人费解。如果我忘记了一两个字符就需要更改它,这不太实用。
  2. 第二种解决方案更好、更简洁,但它可能比实际匹配的要多得多。我找不到任何实际的文件究竟是什么.比赛,(在从表中“任何除换行符字符”的只是概括MDN)。
  3. 第三种解决方案似乎是最精确的,但是有什么问题吗?我不是很熟悉的Unicode,在实践中至少,但看着码表/该表的延续\u00C0-\u017F似乎是非常稳固,至少在我的预期输入。

    • 教职员工不会用他们的母语(例如阿拉伯语、中文、日语等)提交带有他们名字的表格,所以我不必担心拉丁字符集以外的字符

所以真正的问题是:这三种方法中的哪一种最适合这项任务?或者有更好的解决方案吗?

6个回答

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

[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 [ ] ^ \ × ÷

有关按数字顺序列出的字符,请参阅https://unicode-table.com/en/

@PierreHenry-定义了一个范围,这种技术利用字符集中字符的顺序来定义一个连续的范围,从而为问题提供了一个超级简洁的解决方案
2021-03-14 14:00:03
这至少与字符 [、]、^ 和 \ 匹配,其中任何一个都不应该包含在内。
2021-03-19 14:00:03
它工作得很好,+1,但你能详细说明它为什么工作吗?
2021-03-29 14:00:03
这会不会比赛下划线(之间的其他非单词字符Za)?
2021-03-30 14:00:03
不起作用,此范围内的少数字符不是重音字符(例如,U+00D7 是乘号)请参阅:unicode-table.com/en
2021-04-01 14:00:03

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

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

我添加了这些代码块(\u00C0-\u024F一次包括三个相邻的块):

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

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

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

最初的正则表达式停在\u017Fborked 名称“Șenol”上。根据FontSpace 的 Unicode Analyzer,第一个字符是\u0218, LATIN CAPITAL LETTER S WITH COMMA 下面。(是的,它通常用 cedilla-S 拼写\u015E,“Şenol。”但我不会飞到土耳其去告诉他,“你的名字拼错了!”)

看看unicode table latin block,我认为你还应该包括 \u1e00-\u1eff,所以我正在做[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]
2021-03-16 14:00:03
这是同样的事情,但有字形:[a-zA-ZÀ-ÖÙ-öù-ÿĀ-žḀ-ỿ0-9].
2021-03-21 14:00:03

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

取决于任务:-) 要准确匹配所有拉丁字符及其重音版本,Unicode 范围可能提供了最佳解决方案。它们可能会扩展到所有非空白字符,这可以使用\S字符类来完成

我正在强制用户界面中的字段匹配格式:(last_name, first_name最后一个 [逗号空格] 首先)

我在这里看到的最基本的问题不是变音符号,而是空格。有一些名称由多个词组成,例如标题。因此,您应该使用最通用的方法,即允许除区分名字和姓氏的逗号之外的所有内容:

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

但是您使用.字符类的第二个解决方案也一样好,您可能只需要关心多个逗号。

啊,所以它读起来更像any_character_not_a_comma, any_character_not_a_comma这就是我第一次阅读时的想法,当我看到其中的三个逗号时,我有点困惑。
2021-03-28 14:00:03
嗯,也许你是对的。我可能把它复杂化了……你能解释一下你提供的正则表达式吗?我已经使用正则表达式有一段时间了,但只是基本的东西,而且我真的不知道你的实际上是做什么的!
2021-04-01 14:00:03
这是一个否定的字符类- 意思是“除了逗号之外的任何东西”。
2021-04-01 14:00:03
@MateoTibaquirá 您可以简化[^\s]\S
2021-04-02 14:00:03
对,就是这样。很抱歉对s空白的缺失感到困惑......
2021-04-03 14:00:03

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>

问题的评论中提到了它,但很容易错过。我是在提交这个答案后才注意到的。

很好,事实证明我实际上并不需要在 unicode 上使用正则表达式,而是在 pattern 上anything, anything这对未来的读者很有用:)
2021-03-11 14:00:03

这个怎么样?

/^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/
不匹配Šš
2021-03-13 14:00:03
@Gajus 然后将这两个放在字符类中!
2021-03-22 14:00:03
@pacoverflow 关注的不是 Šš 是否专门匹配,而是如果它们不匹配,那么问题就变成了还有什么不匹配。
2021-04-06 14:00:03