为什么针对西里尔字母的正则表达式会漏掉一个字母?

5

我希望在一个HTML页面中验证文本输入字段,只接受西里尔字母。我已经使用正则表达式在JavaScript中编写了验证代码,像这样:

var namevalue = document.getElementById("name")
var letters = /^[А-Яа-я]+$/;
if (namevalue.matches(letters)) {
  alert("Accepted");
}
else {
  alert("Enter only cyrillic letters");
}

这段代码适用于所有西里尔字母,但不包括Ё和ё。


1
尝试这个:var letters = /^[А-Яа-яёЁ]+$/; - Mark Zucchini
@MarkZucchini:字符类不是这样工作的。请删除 | - Cerbrus
这可能会有所帮助:http://en.wikipedia.org/wiki/Cyrillic_script#Computer_encoding - nhahtdh
3
“仅限西里尔字母”这个要求比较含糊,因为有很多语言使用西里尔字母的子集,而某个语言中有效的字符在另一个语言中可能不存在。您试图匹配的是哪种语言? - georg
1
是的。问题在于 ё 没有起作用,因为它超出了 A-Я 的范围。A-Я 是基本的西里尔字母表[0430-044F],但 ё 不属于该基本字母表。它属于西里尔扩展字母[0400-045F]。因此,JavaScript 正则表达式的比较不是通过字母本身,而是通过其字符编码进行的,所以 ё 超出了范围。 - Mark Zucchini
@MarkZucchini,把你的评论变成答案,这将是正确的,假设“西里尔字母”意味着“现代俄语中使用的字母”,这显然是意图。 - Jukka K. Korpela
3个回答

3
问题在于ё无法工作,因为它超出了Aа-Яя的范围。 Aа-Яа属于基本西里尔字母表[0430-044F],但ё不属于该基本西里尔字母表ё属于西里尔扩展区[0400-045F]。因为JavaScript正则表达式引擎比较的是字符码而不是字母本身,所以ё超出了范围。
我假设您的意思是现代俄语,尽管ё很少使用,但仍然广泛使用,我可以建议以下解决方案。
var namevalue = document.getElementById("name")

// please note that I added to your pattern "еЁ".
// now this matches all Russian cyrillic letters both small and caps
// plus ё and Ё
var letters = /^[А-Яа-яёЁ]+$/; 

if (namevalue.matches(letters)) {
   alert("Accepted");
}
else {
   alert("Enter only cyrillic letters");
} 

不幸的是,A-ЯЁ的问题深藏在Unicode规范中。没有简单明了的解决方案。因此,为了编写健壮的程序,您需要时刻准备好处理这种情况。


2
由于JS确保正确的大小写折叠,因此可以简单地使用/^[а-яё]+$/i - georg

1

你可以在西里尔字母扩展中找到 ёЁ,而不是在 А-Яа-я 中找到。


1

Ë不一定在西里尔字母表中,因此不会被你使用的А-Яа-я范围所捕获。

你的Ë是西里尔字母吗:U+0401还是拉丁字母:U+00CB

如果您还想捕获非西里尔字母的Ë,您可能需要将此范围添加到您的正则表达式中:À-ÿ

alert(JSON.stringify("Ëë".match(/^[À-ÿ]+$/)))

如果您只想捕获西里尔字母中的Ë,请尝试以下方法:
不要从U+0410А)开始您的范围,而是从U+0400Ѐ)开始,并在U+045Fџ)结束:

alert(JSON.stringify("Ёё".match(/^[Ѐ-џ]+$/)))

(这个范围应该包括完整的西里尔字母表。)
来源:Unicode字符代码 您可以使用此页面检查需要添加到正则表达式中的范围。

1
我不确定如何描述第一个选项。它在视觉上类似于西里尔字母的e umlaut(U+0451),但它是拉丁文(不太可能与西里尔文混合)。我认为你的第二个解决方案可能是OP想要的,但它将包括一堆未使用的西里尔字符。 - nhahtdh
是的,这有些棘手。我不熟悉西里尔文,所以我不知道哪些字符被使用,哪些没有被使用。如果您熟悉,请建议更好的使用范围 :-) - Cerbrus
1
除非你只想迎合一种语言,否则你总会有未使用的西里尔字母。它们在某些语言中都被使用(否则它们就不存在了!),但没有任何单一的语言使用它们全部。 - blgt
在这种情况下,拉丁字母Ë是无关紧要的。如果您想允许具有与西里尔字母相同形状的拉丁字母,则需要允许更多内容;特别允许拉丁Ë将非常奇怪。答案的另一部分问题在于任意允许一组西里尔字母,拒绝其中许多字母。表达式并不代表所有西里尔字母,但它也不代表用于俄语的字母集,这显然是意图。 - Jukka K. Korpela
@JukkaK.Korpela:不要只是告诉我我做错了,能否提供一个替代方案的建议? - Cerbrus
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接