正则表达式只接受波斯字符

时间:2014-03-21 17:07:32

标签: c# asp.net regex unicode

我正在处理一个表单,其中一个自定义验证程序应该只接受波斯语字符...我使用了以下代码:

    var myregex = new Regex(@"^[\u0600-\u06FF]+$");
    if (myregex.IsMatch(mytextBox.Text))
    {
        args.IsValid = true;
    }
    else
    {
        args.IsValid = false;
    }

但它似乎只适用于检查阿拉伯字符而且它不包括所有波斯字符(它缺少这四个گ,چ,پ,ژ)...有没有办法解决这个问题?

8 个答案:

答案 0 :(得分:44)

TL; DR

波斯语必须使用的字符集如下:

  • 使用^[آابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی]+$表示字母或使用有关正则表达式的代码点(并非所有引擎都支持\uXXXX表示法):

    ^[\u0622\u0627\u0628\u067E\u062A-\u062C\u0686\u062D-\u0632\u0698\u0633-\u063A\u0641\u0642\u06A9\u06AF\u0644-\u0648\u06CC]+$
    
  • 使用^[۰۱۲۳۴۵۶۷۸۹]+$表示数字或关于正则表达式的风格:

    ^[\u06F0-\u06F9]+$
    
  • [ ‬ٌ ‬ًّ ‬َ ‬ِ ‬ُ ‬ْ ‬]用于元音或关于正则表达式的风格:

    [\u202C\u064B\u064C\u064E-\u0652]
    

或这些的组合。您可能希望将其他阿拉伯字母(如Hamza ء)添加到您的字符集中。

为什么[\u0600-\u06FF][آ-ی]都错了?

虽然\u0600-\u06FF包括:

    带有代码点گ
  • 06AF 带有代码点چ
  • 0686 带有代码点پ
  • 067E 带有代码点ژ
  • 0698

同样,所有建议[\u0600-\u06FF][آ-ی]的答案都是错误的。

  

即。 \u0600-\u06FF包含209个字符,超出您的需要!它也包括数字!

enter image description here

全文

这个答案的存在是为了解决一个常见的误解。代码点060006FF不代表 Persian / Farsi alphabet [آ-ی]也没有):

[\u0600-\u0605 ؐ-ؚ\u061Cـ ۖ-\u06DD ۟-ۤ ۧ ۨ ۪-ۭ ً-ٕ ٟ ٖ-ٞ ٰ ، ؍ ٫ ٬ ؛ ؞ ؟ ۔ ٭ ٪ ؉ ؊ ؈ ؎ ؏
۞ ۩ ؆ ؇ ؋ ٠۰ ١۱ ٢۲ ٣۳ ٤۴ ٥۵ ٦۶ ٧۷ ٨۸ ٩۹ ءٴ۽ آ أ ٲ ٱ ؤ إ ٳ ئ ا ٵ ٮ ب ٻ پ ڀ
ة-ث ٹ ٺ ټ ٽ ٿ ج ڃ ڄ چ ڿ ڇ ح خ ځ ڂ څ د ذ ڈ-ڐ ۮ ر ز ڑ-ڙ ۯ س ش ښ-ڜ ۺ ص ض ڝ ڞ
ۻ ط ظ ڟ ع غ ڠ ۼ ف ڡ-ڦ ٯ ق ڧ ڨ ك ک-ڴ ػ ؼ ل ڵ-ڸ م۾ ن ں-ڽ ڹ ه ھ ہ-ۃ ۿ ەۀ وۥ ٶ
ۄ-ۇ ٷ ۈ-ۋ ۏ ى يۦ ٸ ی-ێ ې ۑ ؽ-ؿ ؠ ے ۓ \u061D]

255个字符属于Arabic block(0600-06FF),波斯语字母有32个字母,除了波斯语数字显示它将是42.如果我们添加元音(阿拉伯语元音本来就很少用于没有 Tanvin ًٍِ ‬ٌ ‬)和 Tashdid ّ ‬)的波斯语阿拉伯语变音符号的子集不是波斯语,我们最终会有46个字符。这意味着\u0600-\u06FF包含超过您需要的209个字符!

带有代码点۷

06F7是数字7的波斯语表示,٧代码点0667是相同数字的阿拉伯语表示。 ۶是数字6的波斯语表示,٦是相同数字的阿拉伯语表示。所有这些都位于060006FF代码点。

  

波斯数字四(۴),五(۵)和六(۶)的形状是   不同于阿拉伯语中使用的形状和其他数字   不同的代码点。

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

[آ-ی]也包含117个字符,远远超出了验证所需的字符数。您可以使用 Unicode CLDR 查看所有内容。

答案 1 :(得分:25)

目前你的正则表达式是standard Arabic symbols range。对于其他字符,您需要单独将它们添加到正则表达式。以下是他们的代码:

ژ \u0698
پ \u067E
چ \u0686
گ \u06AF

总而言之,你应该拥有

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

答案 2 :(得分:11)

除了接受的答案(https://stackoverflow.com/a/22565376/790811)之外,我们还应该考虑Zero-width_non-joiner(或波斯语中的نیمفاصله)字符。 不幸的是我们有2个符号。一个是标准的,另一个不是标准的,但广泛使用:

  1. \ u200C:http://en.wikipedia.org/wiki/Zero-width_non-joiner
  2. \ u200F:从右到左标记(http://unicode-table.com/en/#200F
  3. 所以最终 regix可以是:

    ^[\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\u200F]+$
    

    如果您想考虑“空间”,可以使用:

    ^[\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\u200F ]+$
    

    您可以通过以下方式测试JavaScript:

    /^[\u0600-\u06FF\uFB8A\u067E\u0686\u06AF7\u200C\u200F ]+$/.test('ای‌پسر تو چه می‌دانی؟')
    

答案 3 :(得分:6)

注意:persianRex是用Javascript编写的,但你可以使用源代码并复制粘贴字符

由于键盘布局和操作系统的不同,检测波斯字符是一项棘手的任务。我曾经遇到过同样的挑战,我决定编写一个开源库来解决这个问题。

您可以像这样修复您的问题:     persianRex.text.test(yourInput); //返回true或false

这里是完整的文档: http://imanmh.github.io/persianRex/

答案 4 :(得分:3)

波斯语,达里语和塔吉克语都不在我的管辖范围内,但通过Unicode代码图表进行一些翻译告诉我,阿拉伯语涵盖了5个Unicode代码块:

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

您还可以阅读Unicode中的波斯计算:http://behdad.org/download/Publications/persiancomputing/a007.pdf

答案 5 :(得分:2)

我在laravel中使用正则表达式搜索了很多使用波斯字符(如۱۲۳۴)验证波斯电话号码,但没有找到合适的答案,因此我决定将peisan号码更改为英文并自行验证,而不是使用正则表达式验证波斯语号码,这对我有帮助很多,希望这会有所帮助:

if (is_numeric($mobile) && strlen($mobile) == 11) {
      // if number in english
      }else{
            $mobile = str_split($mobile , 2);
            if (count($mobile) != 11) {
                return redirect()->back()->withErrors('فرمت شماره موبایل باید عدد و ۱۱ رقم باشد');
            }
            foreach ($mobile as $key => $number) {
                if ($number == '۰') {
                    $mobile[$key] = 0;
                }elseif ($number == '۱') {
                    $mobile[$key] = 1;
                }elseif ($number == '۲') {
                    $mobile[$key] = 2;
                }elseif ($number == '۳') {
                    $mobile[$key] = 3;
                }elseif ($number == '۴') {
                    $mobile[$key] = 4;
                }elseif ($number == '۵') {
                    $mobile[$key] = 5;
                }elseif ($number == '۶') {
                    $mobile[$key] = 6;
                }elseif ($number == '۷') {
                    $mobile[$key] = 7;
                }elseif ($number == '۸') {
                    $mobile[$key] = 8;
                }elseif ($number == '۹') {
                    $mobile[$key] = 9;
                }
            }
            $mobile = implode($mobile);
            if(is_numeric($mobile) == false){
                return redirect()->back()->withErrors('فرمت شماره موبایل باید عدد و ۱۱ رقم باشد');
            }
        }

答案 6 :(得分:1)

命名块,例如\ p {阿拉伯语}覆盖整个阿拉伯语脚本,而不仅仅是波斯语字符。

演示形式(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)< / LI>
  • 标准阿拉伯语变音符号(U + 064B-U + 0652)
  • 另外两个变音符号(U + 0654,U + 0670)
  • 4个额外的波斯语字符“گچپژ”(U + 067E,U + 0686,U + 0698,U + 06AF)
  • U + 06A9:波斯语Kaf(正式:“阿拉伯语字母Keheh”;与阿拉伯语Kaf不同的符号)
  • U + 06CC:Farsi Yeh(与阿拉伯语Yeh不同)
  • U + 200C:零宽度 - 非连接器

因此,最终的正则表达式将是:

^[\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

答案 7 :(得分:0)

我不确定正则表达式是否可以这样做,但问题并不仅限于波斯语或阿拉伯语,中文,俄语文本。所以也许您可以看到character is existing in your Codepage,如果不在代码页中,那么我怀疑用户是否可以使用输入设备插入它们....

 var encoding = Encoding.GetEncoding(1256);
 var expect = "گ چ پ ژ";
 var actual= encoding.GetBytes("گ چ پ ژ");
 Assert.AreEqual(encoding.GetString(actual),expect);

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