使用Regex解析C#中的字符串

时间:2018-09-26 00:11:12

标签: c# regex

需要解析:

/subscriptions/1234/resourceGroups/5678/providers/BlaBlaBla/workspaces/BluBluBlu

并提取变量:

  • 1234
  • 5678
  • BlaBlaBla
  • BluBluBlu

如何使用C#和正则表达式以一种简洁的方式做到这一点?

3 个答案:

答案 0 :(得分:4)

单行代码

var bits = noodly.Split('/');

答案 1 :(得分:2)

如果仍然需要正则表达式,并且与其他位置一样需要定位,则可以对此正则表达式使用 Capture Collection

^(?:/[^/]*/([^/]*))+

这些项目在组1的捕获集合中。

答案 2 :(得分:1)

这不是要回答,而是给未来的读者(我很无聊)

正则表达式

return Regex.Matches(input, @"^(?:/[^/]*/([^/]*))+")[0]
            .Groups[1]
            .Captures.Cast<Capture>()
            .Select(m => m.Value)
            .ToArray();

regexCompiled

private static readonly Regex regex = new Regex(@"^(?:/[^/]*/([^/]*))+", RegexOptions.Compiled);
...

return regex.Matches(input)[0]
            .Groups[1]
            .Captures.Cast<Capture>()
            .Select(m => m.Value)
            .ToArray();

拆分

return input.Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries)
            .Skip(1)
            .Where((x, i) => i % 2 == 0)
            .ToArray();

不安全

var list = new List<string>();
var result = string.Empty;

fixed (char* pInput = input)
{
   var plen = pInput + input.Length;
   var toggle = true;

   for (var p = pInput; p < plen; p++)
   {
      if (*p == '/')
      {       
         if (result.Length > 0)
            list.Add(result);
         toggle = !toggle;
         result = string.Empty;
         continue;
      }
      if (toggle)
         result += *p;
   }
}
list.Add(result);
return list.ToArray();

基准

----------------------------------------------------------------------------
Mode             : Release (64Bit)
Test Framework   : .NET Framework 4.7.1 (CLR 4.0.30319.42000)
----------------------------------------------------------------------------
Operating System : Microsoft Windows 10 Pro
Version          : 10.0.17134
----------------------------------------------------------------------------
CPU Name         : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
Description      : Intel64 Family 6 Model 58 Stepping 9
Cores (Threads)  : 4 (8)      : Architecture  : x64
Clock Speed      : 3901 MHz   : Bus Speed     : 100 MHz
L2Cache          : 1 MB       : L3Cache       : 8 MB
----------------------------------------------------------------------------

结果

--- Random characters -------------------------------------------------------
| Value         |  Average |  Fastest |   Cycles | Garbage | Test |    Gain |
--- Scale 1 -------------------------------------------------- Time 0.152 ---
| unsafe        | 2.131 µs | 1.461 µs | 10.567 K | 0.000 B | Pass | 78.42 % |
| split         | 3.874 µs | 2.922 µs | 16.804 K | 0.000 B | Pass | 60.76 % |
| regexCompiled | 7.313 µs | 5.845 µs | 29.310 K | 0.000 B | Pass | 25.93 % |
| regex         | 9.873 µs | 7.891 µs | 37.800 K | 0.000 B | Base |  0.00 % |
-----------------------------------------------------------------------------

摘要

对反映原始模式的不同字符串组合分别测试了1,000,000次。

不安全是jsut荒谬的,不应该使用,Regex整洁,拆分也不是太难以理解。如预期的那样分裂更快。

但是,正则表达式没有我想的那么慢。最后,它归结为persoanl性能和您的代码审阅者。

更新

正如 sln 在评论中正确提到的,应该编译正则表达式以使其成为一个良好的基准。请注意,我省略了基本上保留.Groups[1].Captures.Cast<Capture>().Select(m => m.Value).ToArray();的建议,只是将结果保留为字符串数组以使它们保持相同。

IL的编译使regex性能良好。

免责声明 ,我对正则表达式一无所知,并一直使用它