关于c#:regex,仅接受波斯字符

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 ?

为什么[\\u0600-\\u06FF][?-?]都错误?

尽管\\u0600-\\u06FF包括:

  • ?与代码点06AF
  • ?与代码点0686
  • ?与代码点067E
  • ?与代码点0698

同样,所有提示[\\u0600-\\u06FF][?-?]的答案都是错误的。

i.e. \\u0600-\\u06FF contains 209 more characters than you need! and it includes numbers too!

enter image description here

整个故事

存在此答案以解决常见的误解。代码点060006FF不表示波斯/波斯字母([?-?]均不):

1
2
3
4
5
[\\u0600-\\u0605 ?-?\\u061C? ?-\\u06DD ?-? ? ? ?-? ?-? ? ?-? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?-? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-? ? ? ? ?-? ? ? ? ?-? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ?-? ? ? ? ? ? ?-? ? ? ? ?-? ?? ? ?-? ? ? ? ?-? ? ?? ?? ?
?-? ? ?-? ? ? ?? ? ?-? ? ? ?-? ? ? ? \\u061D]

255个字符落在阿拉伯语块(0600–06FF)下,波斯语字母还有32个字母,除了波斯语数字显示外,它还会是42个字母。如果我们添加元音(最初是阿拉伯语的元音,在波斯语中很少使用)而没有丹文(< x4>,?? ?? ?)和Tashdid(? ?)都是阿拉伯变音符号而不是波斯字母符号的子集,我们最终得到46个字符。这意味着\\u0600-\\u06FF包含的字符数超过了您需要的209个!

代码点为06F7?是数字7的波斯表示,而代码点为0667?是相同数字的阿拉伯表示。 ?是数字6的波斯表示,而?是相同数字的阿拉伯表示。所有都通过06FF代码点驻留在0600中。

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.

您会看到波斯语/波斯语中不存在的其他数量不同的其他字符,并且在验证名字或姓氏时没有人愿意拥有它们。

[?-?]也包含117个字符,这远远超过了验证所需的字符。您可以使用Unicode CLDR看到它们。


您当前在正则表达式中使用的是标准阿拉伯符号范围。对于其他字符,您需要将它们分别添加到正则表达式中。这是他们的代码:

1
2
3
4
? \\u0698
? \\u067E
? \\u0686
? \\u06AF

所以总的来说你应该有

1
^[\\u0600-\\u06FF\\u0698\\u067E\\u0686\\u06AF]+$


除了可接受的答案(https://stackoverflow.com/a/22565376/790811),我们还应该考虑零宽度非连接符(或波斯语中的??? ??????)字符。
不幸的是,我们有2个符号。一个是标准的,另一个不是标准的,但被广泛使用:

  • \ u200C:http://en.wikipedia.org/wiki/Zero-width_non-joiner
  • \ u200F:从右到左的标记(http://unicode-table.com/en/#200F)
  • 所以最终的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

    您可以使用命名块而不是显式代码点范围在正则表达式中使用它们(至少其中一些):\\p{IsArabicPresentationForms-A}将为您提供前面列表中的第4个Unicode块。

    您可能还会阅读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);

    该测试将测试往返行程,其中输入应将字符串与字节匹配并返回。该链接显示了受支持的代码页。