代码之家  ›  专栏  ›  技术社区  ›  Didac Perez Parera

使用regex分析C中的字符串

  •  -1
  • Didac Perez Parera  · 技术社区  · 6 年前

    需要解析:

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

    并提取变量:

    • 一千二百三十四
    • 五千六百七十八
    • 布莱布拉
    • 蓝布鲁姆

    如何使用C和正则表达式以一种干净的方式完成这项工作?

    3 回复  |  直到 6 年前
        1
  •  1
  •   TheGeneral    6 年前

    这不是为了回答,而是为了将来的读者(我觉得无聊)

    正则表达式

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

    正则表达式编译

    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 % |
    -----------------------------------------------------------------------------
    

    总结

    在反映原始模式的不同字符串组合上测试了1000000次。

    不安全是jsut的荒谬,不应该使用,regex是整洁的,拆分也不太可读。随着选择的分割速度加快。

    然而,regex并不像我想象的那么慢。最后,它归结为Persoanl性能和您的代码评审器。

    更新

    AS SLN 在一条评论中正确地提到,应该编译regex以使其成为一个好的基准。注意,我遗漏了把 .Groups[1].Captures.Cast<Capture>().Select(m => m.Value).ToArray(); 基本上,只需要给结果留下一个字符串数组来保持它们的一致性。

    对IL的编译可以提高regex的性能。

    免责声明 ,我对regex没有任何反对意见,一直使用它

        2
  •  4
  •   pm100    6 年前

    单行代码

    var bits = noodly.Split('/');
    
        3
  •  2
  •   sln    6 年前

    如果仍然需要regex和if positional,就像其他的一样,可以使用 捕获集合 用这个正则表达式。

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

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