regex for accepting only persian characters
我正在使用一种表单,其中其自定义验证器之一应仅接受波斯字符。 我使用以下代码:
1 2 3 4 5 6 7 8 9 | var myregex = new Regex(@"^[\\u0600-\\u06FF]+$"); if (myregex.IsMatch(mytextBox.Text)) { args.IsValid = true; } else { args.IsValid = false; } |
但是,它似乎只能检测阿拉伯字符,因为它不能覆盖所有波斯字符(它缺少以下四个字符:?,?,?,?)。
有办法解决这个问题吗?
TL; DR
波斯语必须使用的字符集如下:
-
使用
^[?????????????????????????????????]+$ 表示字母或使用与正则表达式风格有关的代码点(并非所有引擎都支持\\uXXXX 表示法):1^[\\u0622\\u0627\\u0628\\u067E\\u062A-\\u062C\\u0686\\u062D-\\u0632\\u0698\\u0633-\\u063A\\u0641\\u0642\\u06A9\\u06AF\\u0644-\\u0648\\u06CC]+$ -
将
^[??????????]+$ 用于数字或关于正则表达式的风格:1^[\\u06F0-\\u06F9]+$ -
将
[ ?? ??? ?? ?? ?? ?? ?] 用于元音或关于正则表达式的味道:1[\\u202C\\u064B\\u064C\\u064E-\\u0652]
或这些的组合。您可能需要在字符集中添加其他阿拉伯字母,例如Hamza
为什么
尽管
-
? 与代码点06AF -
? 与代码点0686 -
? 与代码点067E -
? 与代码点0698
同样,所有提示
i.e.
\\u0600-\\u06FF contains 209 more characters than you need! and it includes numbers too!
整个故事
存在此答案以解决常见的误解。代码点
1 2 3 4 5 | [\\u0600-\\u0605 ?-?\\u061C? ?-\\u06DD ?-? ? ? ?-? ?-? ? ?-? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-? ? ? ? ?-? ? ? ? ?-? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-? ? ? ? ? ? ?-? ? ? ? ?-? ?? ? ?-? ? ? ? ?-? ? ?? ?? ? ?-? ? ?-? ? ? ?? ? ?-? ? ? ?-? ? ? ? \\u061D] |
255个字符落在阿拉伯语块(0600–06FF)下,波斯语字母还有32个字母,除了波斯语数字显示外,它还会是42个字母。如果我们添加元音(最初是阿拉伯语的元音,在波斯语中很少使用)而没有丹文(< x4>,
代码点为
The shapes of the Persian digits four (
? ), five (? ), and six (? ) are
different from the shapes used in Arabic and the other numbers have
different codepoints.
您会看到波斯语/波斯语中不存在的其他数量不同的其他字符,并且在验证名字或姓氏时没有人愿意拥有它们。
您当前在正则表达式中使用的是标准阿拉伯符号范围。对于其他字符,您需要将它们分别添加到正则表达式中。这是他们的代码:
1 2 3 4 | ? \\u0698 ? \\u067E ? \\u0686 ? \\u06AF |
所以总的来说你应该有
1 | ^[\\u0600-\\u06FF\\u0698\\u067E\\u0686\\u06AF]+$ |
除了可接受的答案(https://stackoverflow.com/a/22565376/790811),我们还应该考虑零宽度非连接符(或波斯语中的??? ??????)字符。
不幸的是,我们有2个符号。一个是标准的,另一个不是标准的,但被广泛使用:
所以最终的regix可以是:
1 | ^[\\u0600-\\u06FF\\uFB8A\\u067E\\u0686\\u06AF\\u200C\\u200F]+$ |
如果要考虑"空间",可以使用以下方法:
1 | ^[\\u0600-\\u06FF\\uFB8A\\u067E\\u0686\\u06AF\\u200C\\u200F ]+$ |
您可以通过以下方式对其进行测试:
1 | /^[\\u0600-\\u06FF\\uFB8A\\u067E\\u0686\\u06AF7\\u200C\\u200F ]+$/.test('?????? ?? ?? ????????') |
注意:persianRex用Java编写,但是您可以使用源代码并复制粘贴字符
由于具有多种键盘布局和操作系统,因此检测波斯字符是一项棘手的任务。我之前曾遇到过同样的挑战,因此我决定编写一个开放源代码库来解决此问题。
您可以这样解决问题:
persianRex.text.test(yourInput); //返回true或false
这是完整的文档:
http://imanmh.github.io/persianRex/
命名的块,例如\ p {Arabic}覆盖整个阿拉伯语脚本,而不仅仅是波斯字符。
表示形式(u + FB50-u + FDF??F)不应在文本中使用,而应转换为标准范围(u + 0600-u + 06FF)。
为了仅涵盖波斯语,我们需要以下内容:
- 波斯语字符超出标准阿拉伯语范围的子集,即(U + 0621-U + 0624,U + 0626-U + 063A,U + 0641-U + 0642,U + 0644-U + 0648)
- 标准阿拉伯语变音符号(U + 064B-U + 0652)
- 另外2个变音符号(U + 0654,U + 0670)
- 额外的4个波斯语字符"????" (U + 067E,U + 0686,U + 0698,U + 06AF)
- U + 06A9:波斯语卡夫语(原名:"阿拉伯字母Keheh";与阿拉伯语卡夫语不同的符号)
- U + 06CC:Farsi Yeh(与阿拉伯语Yeh不同的表示法)
- U + 200C:零宽度非连接器
因此,生成的正则表达式将是:
1 | ^[\\u0621-\\u0624\\u0626-\\u063A\\u0641-\\u0642\\u0644-\\u0648\\u064B-\\u0652\\u067E\\u0686\\u0698\\u06AF\\u06CC\\u06A9\\u0654\\u670\\u200c}]+$ |
另请参见此处列出的波斯语示例字符:
http://unicode.org/cldr/trac/browser/trunk/common/main/fa.xml
波斯语,达里语和塔吉克语不在我的视线范围内,但是在Unicode代码表中翻找一番,便发现阿拉伯语涵盖了5个Unicode代码块:
- 阿拉伯语:http://www.unicode.org/charts/PDF/U0600.pdf
- 阿拉伯文补编:http://www.unicode.org/charts/PDF/U0750.pdf
- 阿拉伯文扩展A:http://www.unicode.org/charts/PDF/U08A0.pdf
- 阿拉伯文演示文稿表格-A:http://www.unicode.org/charts/PDF/UFB50.pdf
- 阿拉伯文演示文稿表格B:http://www.unicode.org/charts/PDF/UFE70.pdf
您可以使用命名块而不是显式代码点范围在正则表达式中使用它们(至少其中一些):
您可能还会阅读Unicode中的波斯计算:http://behdad.org/download/Publications/persiancomputing/a007.pdf
我不确定正则表达式是否可以做到这一点,但是问题不仅仅限于波斯语或阿拉伯语,中文,俄文。因此,也许您可??以看到代码页中是否存在该字符,如果代码页中不存在该字符,那么我怀疑用户是否可以使用输入设备将其插入...。
1 2 3 4 | var encoding = Encoding.GetEncoding(1256); var expect ="? ? ? ?"; var actual= encoding.GetBytes("? ? ? ?"); Assert.AreEqual(encoding.GetString(actual),expect); |
该测试将测试往返行程,其中输入应将字符串与字节匹配并返回。该链接显示了受支持的代码页。