RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 872586
Accepted
Evgeniy Miroshnichenko
Evgeniy Miroshnichenko
Asked:2020-08-23 21:47:20 +0000 UTC2020-08-23 21:47:20 +0000 UTC 2020-08-23 21:47:20 +0000 UTC

正则表达式“\p{N}+”不匹配数字字符

  • 772

根据 C# 文档:

C# 中的正则表达式支持常见的 Unicode 类别,包括:

Nd - 数字:十进制数字

Nl - 数字:字母

否 - 编号:其他

N - 所有数字。包括类别 Nd、Nl 和 No。

为了测试一个正则表达式\p{N}可以包含类别 Nd、Nl 和 No 的断言,我编写了一个可以获取类别 N 的完整字符集的代码:

// Get all Unicode groups:
Dictionary<UnicodeCategory, IGrouping<UnicodeCategory, string>> charInfo = (
      Enumerable.Range(0, 0x110000)
          .Where  (x => (x < 0x00D800 || x > 0x00DFFF))
          .Select (Char.ConvertFromUtf32)
          .GroupBy(s => Char.GetUnicodeCategory(s, 0))
          .ToDictionary(g => g.Key)
);

// Get all number unicode groups:
string[] Nd = charInfo[UnicodeCategory.DecimalDigitNumber].ToArray();
string[] Nl = charInfo[UnicodeCategory.LetterNumber      ].ToArray();
string[] No = charInfo[UnicodeCategory.OtherNumber       ].ToArray();

string[] N = Nd.Union(Nl).Union(No).ToArray();

通过NUnit 测试中N的正则表达式运行生成的组字符集:

Regex.IsMatch(symbol, @"\p{N}+", RegexOptions.Multiline);

我得到的结果是数组 N 的一半字符没有通过方法的测试Regex.IsMatch()。

未通过测试的字符示例:𐒠、𐒡。他们中的大多数看起来像:𖭖

你能告诉我为什么正则表达式不能识别属于“数字”类别的字符\p{N}+吗?

c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Wiktor Stribiżew
    2020-10-06T07:41:53Z2020-10-06T07:41:53Z

    简而言之...

    Char对象的值是一个 16 位数字(序数)值。UTF-16 编码的字符串允许代理对由高位和低位通配符组成,每个都是类型的变量char。如果我们计算这样一个字符的长度,str.Length它将返回2. 在英语中,这样的𝟬符号被定义为一个“代码点”,它由两个“代码单元”\ud835和组成\udfec。

    .NET 中的正则表达式不支持代理对,也就是说,它们在“代码单元”级别工作。这些对中的每一对都是正则表达式引擎的 16 位字节的正常序列。为了找到它们,您需要将这些序列指定为字符类中的范围。

    这种正则表达式的演示,查找所有数字字符:

    \p{N}|\ud801[\udca0-\udca9]|\ud804[\udc66-\udc6f\udcf0-\udcf9\udd36-\udd3f\uddd0-\uddd9\udef0-\udef9\udc52-\udc65\udde1-\uddf4]|\ud805[\udcd0-\udcd9\ude50-\ude59\udec0-\udec9\udf30-\udf3b]|\ud806[\udce0-\udcf2]|\ud81a[\ude60-\ude69\udf50-\udf59\udf5b-\udf61]|\ud835[\udfce-\udfff]|\ud800[\udd40-\udd74\udf41\udf4a\udfd1-\udfd5\udd07-\udd33\udd75-\udd78\udd8a\udd8b\udee1-\udefb\udf20-\udf23]|\ud809[\udc00-\udc6e]|\ud802[\udc58-\udc5f\udc79-\udc7f\udca7-\udcaf\udcfb-\udcff\udd16-\udd1b\uddbc\uddbd\uddc0-\uddcf\uddd2-\uddff\ude40-\ude47\ude7d\ude7e\ude9d-\ude9f\udeeb-\udeef\udf58-\udf5f\udf78-\udf7f\udfa9-\udfaf]|\ud803[\udcfa-\udcff\ude60-\ude7e]|\ud834[\udf60-\udf71]|\ud83a[\udcc7-\udccf]|\ud83c[\udd00-\udd0c]
    

    构建和测试模板

    我已经声明了以下变量:

    var chrLst = new List<KeyValuePair<char, char>>(); // список суррогатных пар со старшим и младшим знаком
    var testList = new List<string>(); // список символов для тестирования
    var N_pattern_groups = new List<string>(); // список для создания шаблона регулярного выражения
    

    N然后我通过以下代码运行所有字符:

    foreach (var symbol in N)
    {
        if (!Regex.IsMatch(symbol, @"\p{N}"))
        {
            testList.Add(symbol); // заполняем список тестируемых символов
            var chrs = symbol.ToCharArray();
            chrLst.Add(new KeyValuePair<char, char>(chrs[0], chrs[1])); // Заполняем список суррогатных пар
            var hex = string.Concat(chrs.Select(x => string.Format(@"\u{0:x4}", (int)x))); // Получаем строку шестнадцатеричных значение обоих знаков 
            file.WriteLine($"{symbol}\t{hex}\t{char.IsSurrogatePair(symbol, 0)}"); // Сохранил информацию о символе в файл
        }
    }
    

    调试文件在 MS Visual Studio 2017 中运行时包含 708 个字符,但在 ideone.com 上的 C# Mono 中仅包含 443 个字符。

    接下来,您需要构建一个模板。为此,我们将带有键和值的列表按键分组,构建一系列值并将所有内容组合成一个正则表达式:

    var groups = chrLst.GroupBy(x => x.Key);
    foreach (var grp in groups)
    {
        N_pattern_groups.Add(string.Format(@"\u{0:x4}", (int)grp.Key) + CreateRangesFromList(grp.Select(x => x.Value).ToList()));
    }
    var N_pattern = string.Join("|", N_pattern_groups);
    Console.WriteLine($"Pattern: {N_pattern}"); // Этот шаблон без \p{N}| приведён выше
    

    该方法CreateRangesFromList看起来不是最好的,但它可以完成工作:

    private string CreateRangesFromList(List<char> chrs)
    {
        var tmp = "";
        var rngnum = 0;
        for (var i = 0; i < chrs.Count; i++)
        {
            if ((i < chrs.Count - 1) && (int)chrs[i] == ((int)chrs[i + 1]) - 1) {
                if (rngnum == 0)
                {
                    tmp += string.Format(@"\u{0:x4}", (int)chrs[i]);
                }
                rngnum++;
            }
            else 
            {
                tmp += (rngnum > 1 ? "-" : "") + string.Format(@"\u{0:x4}", (int)chrs[i]);
                rngnum = 0;
            }
        }
        return $"[{tmp}]";
    }
    

    检查帮助bool check = testList.All(symbol => Regex.IsMatch(symbol, N_pattern));表明一切正常:

    在此处输入图像描述

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5