c# - regex教學 - regular expression performance




\ d效率低於 (4)

我昨天對某個人在正則表達式中使用[0123456789]而不是[0-9]\d的回答發表了評論。 我說使用範圍或數字說明符可能比字符集更有效。

我決定今天測試一下,發現令我驚訝的是(至少在C#正則表達式引擎中) \d看起來效率不如其他兩種似乎差別不大的其他兩種效率更高。 這是我的測試輸出超過1000個隨機字符的10000個隨機字符串,其中5077實際上包含一個數字:

Regular expression \d           took 00:00:00.2141226 result: 5077/10000
Regular expression [0-9]        took 00:00:00.1357972 result: 5077/10000  63.42 % of first
Regular expression [0123456789] took 00:00:00.1388997 result: 5077/10000  64.87 % of first

出於兩個原因,我感到很驚訝:

  1. 我會認為這個系列的實施要比這個系列更有效率。
  2. 我不明白為什麼\d[0-9]更糟糕。 除了簡單的[0-9]之外,還有更多嗎?

以下是測試代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace SO_RegexPerformance
{
    class Program
    {
        static void Main(string[] args)
        {
            var rand = new Random(1234);
            var strings = new List<string>();
            //10K random strings
            for (var i = 0; i < 10000; i++)
            {
                //Generate random string
                var sb = new StringBuilder();
                for (var c = 0; c < 1000; c++)
                {
                    //Add a-z randomly
                    sb.Append((char)('a' + rand.Next(26)));
                }
                //In roughly 50% of them, put a digit
                if (rand.Next(2) == 0)
                {
                    //Replace one character with a digit, 0-9
                    sb[rand.Next(sb.Length)] = (char)('0' + rand.Next(10));
                }
                strings.Add(sb.ToString());
            }

            var baseTime = testPerfomance(strings, @"\d");
            Console.WriteLine();
            var testTime = testPerfomance(strings, "[0-9]");
            Console.WriteLine("  {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
            testTime = testPerfomance(strings, "[0123456789]");
            Console.WriteLine("  {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
        }

        private static TimeSpan testPerfomance(List<string> strings, string regex)
        {
            var sw = new Stopwatch();

            int successes = 0;

            var rex = new Regex(regex);

            sw.Start();
            foreach (var str in strings)
            {
                if (rex.Match(str).Success)
                {
                    successes++;
                }
            }
            sw.Stop();

            Console.Write("Regex {0,-12} took {1} result: {2}/{3}", regex, sw.Elapsed, successes, strings.Count);

            return sw.Elapsed;
        }
    }
}

\ d檢查所有Unicode,而[0-9]僅限於這10個字符。 如果只有10位數字,你應該使用。 其他我推薦使用\ d,因為寫得少。


\d將會效率較低,因為必須進行轉換才能進行比較。

例如,如果我想讓Regex找到IP地址,我寧可用[0123456789]甚至[0-9]來表示任何數字。

一般來說,在我的正則表達式中使用,如果功能比速度更重要。



感謝ByteBlast在文檔中註意到這一點。 只是改變正則表達式的構造函數:

var rex = new Regex(regex, RegexOptions.ECMAScript);

提供新的時機:

Regex \d           took 00:00:00.1355787 result: 5077/10000
Regex [0-9]        took 00:00:00.1360403 result: 5077/10000  100.34 % of first
Regex [0123456789] took 00:00:00.1362112 result: 5077/10000  100.47 % of first




performance