c# - 为什么Regex的Matches函数这么快?

标签 c# regex

<分区>

我的英语水平很差,因为我的母语不是英语。 希望您能理解。

我在 .Net 中使用了 Regex 函数。 有一天,我尝试了用 117000 个字符串和 46 个模式调用 Regex 的 Matches 函数的测试。 结果,生成 51870 个 token 的速度比 2 毫秒快。

令人惊奇的是它只用了 2 毫秒。 将生成的集合转换为 List 花费了 250ms。 (代码如下。)

var list = collection.Cast<Match>().Select(match => match.Value).ToList();

我不敢相信,所以我试了几次,结果都一样。

我很好奇为什么Regex的Matches函数这么快。 它内部使用异步或并行机制吗?

在测试中,我调用了如下函数。

var collection = Regex.Matches(targetString(117000), this.rule(46), RegexOptions.Multiline | RegexOptions.ExplicitCapture);

感谢阅读。


完整的源代码如下。 请在 test.txt 中输入多个字符串。 我删除了“\r”、“\n”、“\t”模式以使其简单。 结果,生成的 token 数量为 45450。 感谢您的关注。

class Program
{
    static void Main(string[] args)
    {
        string targetString = File.ReadAllText("test.txt");

        string pattern = "(\\breturn\\b)|(\\bwhile\\b)|(\\bconst\\b)|(\\belse\\b)|(\\bvoid\\b)|(\\bint\\b)|(\\bif\\b)|" +
    "([_a-zA-Z][_a-zA-Z0-9]*)|([0-9]+)|" +
    "(//.*$)|(\\!\\=)|(\\%\\=)|(\\>\\=)|(\\/\\=)|(\\+\\=)|(\\|\\|)|(\\-\\-)|(\\+\\+)|(\\*\\=)|(\\-\\=)|(\\<\\=)|(\\=\\=)|(\\&\\&)|(\\*\\/)|(\\/\\*)|(\\*)|(\\!)|(\\+)|(\\%)|(\\))|(\\;)|(\\()|(\\/)|" +
    "(\\{)| (\\})| (\\-)| (\\])| (\\[)|(\\,)|(\\>)|(\\ )|(\\=)|(\\<)";


        Stopwatch sw = new Stopwatch();
        sw.Start();

        var collection = Regex.Matches(targetString, pattern, RegexOptions.Multiline | RegexOptions.ExplicitCapture);

        sw.Stop();
        Console.WriteLine("Elapsed={0}", sw.Elapsed);

        sw = new Stopwatch();
        sw.Start();

        var list = collection.Cast<Match>().Select(match => match.Value).ToList();

        sw.Stop();
        Console.WriteLine("Elapsed={0}", sw.Elapsed);
    }
}

我的结果如下所示。

enter image description here

enter image description here

enter image description here

最佳答案

RegExpMatches 方法返回一个包含匹配项的 MatchCollection 对象。但是,此对象默认以惰性 模式运行,这意味着它不会遍历整个字符串并一次找到所有匹配项,而是始终只在必要时找到下一个匹配项。

Documentation :

The MatchCollection object is populated as needed on a match-by-match basis. It is equivalent to the regular expression engine calling the Regex.Match method repeatedly and adding each match to the collection. This technique is used when the collection is accessed through its GetEnumerator method, or when it is accessed using the foreach statement (in C#) or the For Each...Next statement (in Visual Basic).

因此,在您的代码中,实际搜索不是在调用 Matches() 时完成的,而是仅在您尝试将 MatchCollection 转换为 时完成的列表


要测量模式搜索的全部时间,您可以通过访问代码中的 Count 属性来强制直接评估。

Stopwatch sw = new Stopwatch();
sw.Start();

var collection = Regex.Matches(targetString, pattern, RegexOptions.Multiline | RegexOptions.ExplicitCapture);

int count = collection.Count; // Force immediate full evaluation

sw.Stop();
Console.WriteLine("Found {0}, Elapsed={1}", count, sw.Elapsed);

关于c# - 为什么Regex的Matches函数这么快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59120012/

相关文章:

javascript - 用 <br> 替换\n 无效

c# - 从 API 中的引用 token 获取用户 ID

javascript - 查找最后一次出现的正则表达式单词

java - 如何将几个 "Sqrt[some text inside]"变成几个 Sqrt(里面有一些文字),我的意思是从 [] 变成 ()

c# - 检索动态创建的 RadioButtonList 的回发值不起作用

MySQL - 0 或 1 个字符选择查询

java - 正则表达式 - 匹配字符串模式

c# - XNA/MonoGame - 如何使用矩形作为边界框检查列表中每个对象的碰撞

c# - 无法解密使用 AesManaged 加密的文件

c# - 如何通过引用传递 System.Action?