繁体   English   中英

正则表达式环顾

[英]regular expression lookaround

我认为仅使用正则表达式是不可能的,但是我不是专家,所以我认为值得一问。

我正在尝试使用.NET正则表达式进行大量搜索并替换C#代码。 我想做的是找到一行代码,其中在DateTime类型的变量上调用特定函数。 例如:

axRecord.set_Field("CreatedDate", m_createdDate);

而且我知道在代码文件的前面是DateTime变量b / c是这样的:

DateTime m_createdDate;

但似乎我不能像下面这样在否定性后面使用命名组:

(?<=DateTime \k<1>.+?)axRecord.set_[^ ]+ (?<1>[^ )]+)

如果我尝试匹配变量声明和函数调用之间的所有文本,如下所示:

DateTime (?<1>[^;]+).+?axRecord.set.+?\k<1>

它将找到第一个匹配项-首先基于声明的第一个变量-但随后找不到任何其他匹配项,因为代码的布局如下:

DateTime m_First;
DateTime m_Second;
...
axRecord.set_Field("something", m_First);
axRecord.set_Field("somethingElse", m_Second);

第一个匹配项包含第二个变量声明。

是否有一种仅使用正则表达式执行此操作的好方法,还是我必须在逻辑上求助于脚本?

看看我对这个问题的回答从C#文件中获取方法内容

它提供了指向页面的链接,这些页面显示了如何使用内置的.net语言解析器来简单,可靠地执行此操作(即,不是通过询问“我正在寻找的用法”,而是通过使用VS代码正确地解析了代码)解析工具)。

我知道这不是RegEx的答案,但我不认为RegEx是答案。

使用单个正则表达式很难做到这一点。 但是,如果您考虑对状态稍有处理的行,则可以这样做。

注意:我无法在axRecord行上确切告诉您要匹配的内容,因此您可能需要适当地调整该正则表达式。

void Process(List<string> lines) {
  var comp = StringComparer.Ordinal;
  var map = new Hashset<string>comp);
  var declRegex = new Regex("^\s(?<type>\w+)\s*(?<name>m_\w+)\s*";);
  var toReplaceRegex = new Regex("^\s*axRecord.set_(?<toReplace>.*(?<name>m_\w+).*)");

  for( var i = 0; i < lines.Length; i++) {
    var line = lines[i];
    var match = declRegex.Match(line);
    if ( match.Success ) {
      if ( comp.Equals(match.Groups["type"], "DateTime") ) {
        map.Add(comp.Groups["name"]);
      } else {
        map.Remove(comp.Groups["name"]);
      }
      continue;
    }

    match = toReplaceRegex.Match(line);
    if ( match.Success && map.Contains(match.Groups["name"]) ) {
      // Add your replace logic here
    }
}

这不能使用正则表达式来完成。 一方面,C#的语法不规则。 但更重要的是,您正在谈论分析在词汇上不相关的表达式。 对于这种事情,您将需要完整的语义分析。 这意味着词法分析器,解析器,名称绑定以及最后的类型检查器。 获得带注释的AST之后,您可以查找所需的字段,然后直接读取类型。

我猜这比您想做的工作要多得多,因为它大约是成熟的C#编译器的一半。

真奇怪 我设法建立了一个确实找到它的正则表达式,但它仅与第一个匹配。

(?<=private datetime (?<1>\b\w+\b).+?)set_field[^;]+?\k<1>

因此,如果我不能在后备条件中使用命名组,则至少可以在后备条件中建立命名组,并在比赛中使用它。 但是然后看起来像当它仅与函数调用(这就是我想要的)匹配时,插入号位置已移动到该行,因此它找不到任何新匹配项,因为它已传递了它们的声明。 也许我不明白引擎是如何工作的。

我猜我正在寻找的是一个正则表达式选项,它告诉它在匹配项中查找更多匹配项。 想到这一点,似乎也需要基本的html regex解析。 您找到一个标签,然后将其作为结束标签,并且整个页面都包含在该匹配项中,因此除非您递归地将模式应用于每个匹配项,否则您将找不到其他任何标签。

任何人对此一无所知,或者我在疯吗?

尝试这个:

@"(?s)set_Field\(""[^""]*"",\s*(?<vname>\w+)(?<=\bDateTime\s+\k<vname>\b.+)"

通过先进行后向查找,您将强制正则表达式按特定顺序搜索方法调用:变量声明的顺序。 您想要做的是先匹配一个看起来很可能的方法调用,然后使用后向验证变量的类型。

我只是对与方法调用匹配的部分进行了粗略的猜测。 就像其他人所说的那样,无论您使用什么正则表达式都必须根据您的代码量身定制; 没有通用的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM