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

Chr*_*ice 129 javascript regex unicode

我看过Stack Overflow(替换字符......呃,JavaScript如何不遵循关于RegExp的Unicode标准等)并且没有真正找到问题的具体答案:

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

我强迫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àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇߨøÅ寿œ]+$/
Run Code Online (Sandbox Code Playgroud)
  • 这正确地匹配姓氏中的任何支持的重音字符的姓氏/名字accentedCharacters.

我的另一种方法是使用.字符类,以获得更简单的表达式:

var regex = /^.+,\s.+$/;
Run Code Online (Sandbox Code Playgroud)
  • 这几乎可以匹配任何东西,至少以下列形式:something, something.那我觉得好吧......

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

/^[a-zA-Z\u00C0-\u017F]+,\s[a-zA-Z\u00C0-\u017F]+$/
Run Code Online (Sandbox Code Playgroud)
  • 它匹配一系列unicode字符 - 测试和工作,虽然我没有尝试任何疯狂的东西,只是我在语言部门看到的教师成员的正常情况.

以下是我的担忧:

  1. 第一个解决方案太过限制,而且很邋and和错综复杂.如果我忘了一两个字,那就需要改变,这不太实际.
  2. 第二种解决方案更好,更简洁,但它可能比实际应用的更多.我找不到任何实际的文件究竟是什么.比赛,(在从表中"任何除换行符字符"的只是概括MDN).
  3. 第三种解决方案似乎是最精确的,但有任何问题吗?我不是很熟悉Unicode,至少在实践中,但是查看该代码表/延续,\u00C0-\u017F似乎非常可靠,至少对于我的预期输入.

    • 教师不会以他们的母语(例如,阿拉伯语,中文,日语等)提交名称的表格,所以我不必担心拉丁字符集的字符.

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

May*_*ura 205

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

[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 [ ] ^ \ × ÷
Run Code Online (Sandbox Code Playgroud)

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

  • 这至少匹配字符[,],^和\,不应包含任何字符. (20认同)
  • 不会匹配下划线(以及`Z`和`a`之间的其他非单词字符)? (8认同)
  • 阅读评论并看到所有不匹配的重音字母以及所有匹配的非字母,看来这个问题没有好的解决方案。 (4认同)
  • 效果很好,+ 1,但您能否详细说明为什么要这样做? (2认同)
  • @PierreHenry `-` 定义了一个范围,这种技术利用字符集中字符的顺序来定义一个连续的范围,从而为问题提供了一个超级简洁的解决方案 (2认同)
  • 不起作用,此范围内的几个字符不是重音字符(例如 U+00D7 是乘号),请参阅:https://unicode-table.com/en/ (2认同)

Cha*_*ert 29

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

[a-zA-Z\u00C0-\u024F]
[a-zA-Z\u00C0-\u024F\u1E00-\u1EFF] // includes even more Latin chars
Run Code Online (Sandbox Code Playgroud)

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

如果您需要更多代码点,可以在Wikipedia的Unicode字符列表中找到更多范围.例如,您还可以添加Latin Extended-C,DE,但是我将它们排除在外,因为现在只有历史学家对它们感兴趣,而D和E集甚至在我的浏览器中都没有正确呈现.

最初的正则表达式停止在\u00C0-\u00FF名为"Şenol"的borked上.根据FontSpace的Unicode分析器,第一个字符是\u00D7LATIN CAPITAL LETTER S,下面是COMMA.(是的,它通常用cedilla-S拼写\u00F7,"Şenol."但我不是飞往土耳其去告诉他,"你拼错了你的名字!")

  • 看看[unicode table latin block](https://en.wikipedia.org/wiki/List_of_Unicode_characters#Latin_Extended_Additional),我认为你还应该包括\u1e00-\u1eff,所以我在做`[a- zA-Z\u00c0-\u024f\u1e00-\u1eff]` (2认同)
  • 这是同样的事情,但带有字形:“[a-zA-ZÀ-ÖÙ-öù-ÿĀ-žḀ-ỿ0-9]”。 (2认同)

Ber*_*rgi 18

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

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

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

我在这里看到的最基本的问题不是变音符号,而是空格.有几个名称由多个单词组成,例如标题.所以你应该选择最通用的,即允许除逗号之外的所有内容,首先区别于姓氏:

/[^,]+,\s[^,]+/
Run Code Online (Sandbox Code Playgroud)

但是你的第二个解决方案与.角色类一样好,你可能只需要关心多个commata.


tho*_*rn̈ 14

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>
Run Code Online (Sandbox Code Playgroud)

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


alc*_*chn 9

这个怎么样?

/^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/
Run Code Online (Sandbox Code Playgroud)

  • @pacoverflow 关心的不是 Šš 是否具体匹配,而是如果它们不匹配,那么问题就变成还有什么不匹配。 (9认同)
  • 与“Šš”不匹配。 (3认同)

Gaj*_*jus 8

/^[\pL\pM\p{Zs}.-]+$/u
Run Code Online (Sandbox Code Playgroud)

解释:

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

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

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

/^[\pL\pM\p{Zs}.-]+$/u
Run Code Online (Sandbox Code Playgroud)

  • 现在,这应该适用于所有支持 [Unicode 属性转义](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#browser_compatibility) 的 JS 运行时!但你需要稍微调整一下,在“L”和“M”周围添加“{}”:“/[\p{L}\p{M}\p{Zs}.-]+/gu”。这也匹配中文字符,因此如果您只想匹配带有重音符号的*拉丁*字符,请尝试`/[\p{Script=Latin}\p{M}\p{Zs}.-]+/gu`。有关许多有用字符类别的大表,请检查 https://javascript.info/regexp-unicode (9认同)
  • @AhmedFasih 你的评论应该是公认的答案,因为这些转义现在似乎在所有主要浏览器中都有效...... (3认同)

Jav*_*rés 5

那这个呢?

^([a-zA-Z]|[à-ú]|[À-Ú])+$
Run Code Online (Sandbox Code Playgroud)

它将匹配每个带有重音符号的单词。

  • 但是OP希望“允许”带重音符号的字符。 (2认同)

Faw*_*med 5

您可以使用以下方法从字母表中删除变音符号:

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

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

参考:

https://thread.engineering/2018-08-29-searching-and-sorting-text-with-diacritical-marks-in-javascript/

  • 我知道OP正在询问正则表达式,但这是一个可靠的答案并为我解决了问题。请参阅当前投票最高的答案问题[此处](/sf/ask/1268645101/)以获得更完整的解释。 (3认同)