【问题标题】:Regex for retrieving the first parameter of a method call用于检索方法调用的第一个参数的正则表达式
【发布时间】:2013-06-14 03:19:36
【问题描述】:

我正在尝试使用正则表达式中的命名组来捕获方法调用的第一个参数。

例如给定:

.MyMethod(foo);
.MyMethod(foo, bar);
.MyMethod(new MyObject(1, 2), 3);
.MyMethod(new MyObject()).MyChainedMethod();

模式应该返回指定组:

foo
foo
new MyObject(1, 2)
new MyObject()

我尝试了各种组合,但无法匹配每个案例,例如以下匹配第二和第三个案例:

\.MyMethod\((?<firstParam>.+)(?=,|\),)

【问题讨论】:

    标签: .net regex


    【解决方案1】:

    以下应该有效:

    \.MyMethod\((?<firstParam>(?:[^(),]*|\([^)]*\))+)[,)]
    

    示例(和解释):http://regex101.com/r/aS2uR9

    请注意,这适用于您的所有测试用例,也适用于第一个参数的链式函数调用,但是如果您的第一个参数包含嵌套调用,例如.MyMethod(new MyObject(SomeOtherMethod())),它将不起作用。

    您可以通过将\([^)]*\) 部分替换为this answer 中的以下表达式来添加对任意嵌套括号的支持:

    \((?>[^()]+|\((?<Depth>)|\)(?<-Depth>))*(?(Depth)(?!))\)
    

    【讨论】:

    • 谢谢您,这肯定适用于所有必要的情况。
    【解决方案2】:

    你不能。正则表达式无法计算括号,因此您将无法验证打开的括号数是否与闭合的括号数匹配。这是正则表达式的限制,因为它们不能递归。

    构建自己的解析方法并遍历字符串。也许:

    string Parse(string str) {
      int open = 0;
      bool started = false;
      int begin;
      for(int x = 0; x < str.length && (open > 0 || !started); x++) {
        char tok = str[x];
        if (started && tok == '(') open++;
        if (started && tok == ')') open--;
        if (!started && tok == '(') { started = true; open++; begin = x+1; }
      }
      assert(begin < str.length && open == 0);
      return str.substring(begin, x - begin);
    }  
    

    【讨论】:

    • 实际上,C# 正则表达式可以计算任意模式的出现次数。见here。这并不是说正则表达式是解决这个问题的方法......
    【解决方案3】:

    灵感来自this answer:

    \.MyMethod\((?<firstParam>(?:[^(,]|(?<brackets>\()|(?<-brackets>\))|(?(brackets),))*)(?:\)|,)
    

    这是一个复杂的正则表达式,当正则表达式得到这么长的时间时,就需要开始研究专门的解析方法,例如 Jean-Bernard Pellerin 提供的解析方法。

    它是如何工作的:

    \.MyMethod\(                        Basic Text Match for .MyMethod(
    (?<firstParam>                      Capturing group
           (?:[^(,]                       Not a bracket or comma
           |(?<brackets>\()             Or a opening bracket that is added to the 
                                        brackets capturing group
           |(?<-brackets>\))            Or a closing bracket that removes an item 
                                        from the brackets capturing group (failing
                                        if there are no items to remove)
           |(?(brackets),))*)             Or if we have reached a lower level a comma
    (?:\)|,)                           closing bracket or comma
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多