C# 编写正则表达式模式以查找不带Select方法的IQueryable链接方法

C# 编写正则表达式模式以查找不带Select方法的IQueryable链接方法,c#,regex,entity-framework,C#,Regex,Entity Framework,在web应用程序中,我是开发团队的一员,我们使用实体框架作为ORM。当我们执行SQL查询时,通常会链接IQueryable methods实体框架提供的方法,从方法Items()开始,这是我们特定于项目的数据库集模型投影。我一直在尝试编写一个正则表达式模式,该模式将查找不使用Select方法的查询 这就是我们的代码通常的样子 Cars.Items() .Where(x => x.Year == "1988") .Select(x => new { x.Registration

在web应用程序中,我是开发团队的一员,我们使用实体框架作为ORM。当我们执行SQL查询时,通常会链接IQueryable methods实体框架提供的方法,从方法
Items()
开始,这是我们特定于项目的数据库集模型投影。我一直在尝试编写一个正则表达式模式,该模式将查找不使用
Select
方法的查询

这就是我们的代码通常的样子

Cars.Items()
  .Where(x => x.Year == "1988")
  .Select(x => new { x.Registration })
  .ToList();

Cars.Items()
  .Where(x => x.Id == 1923984)
  .Select(x => new { x.Registration })
  .FirstOrDefault;
这就是我想找到的问题

Cars.Items()
  .Where(x => x.Id == 1923984)
  .FirstOrDefault;
我曾尝试使用负前瞻排除具有
Select()
方法的查询,但它们被包括在内,我正在努力寻找替代方法

\.Items\(.*\)(\s*\..*\(.*\))*(?!\.Select\(.+\))(\s*\..*\(.*\))\;
我要打破我的逻辑

  • \.Items\(.*)
    所有查询都以此方法开始
  • (\s*\..*\(.*)*
    任意数量的链链接IQueryable方法
  • (?!\.Select\(.+\)
    应排除
    Select()
    方法
  • (\s*\..*\(.*\)\
    这可以是
    First()
    FirstOrDefault()
    Single()
    或类似的
  • 结束查询

    • 负面展望不起作用的原因是,您已经用此部件捕获了所有内容:

      \.Items\(.*\)(\s*\..*\(.*\)*

      你需要先展望负面,然后包括一切。试试这个正则表达式:

      \.Items\(.*?\)(\W.*(!\)选择\(.+\))(\W.*)\


      在这里尝试一下:

      我也尝试过为此创建正则表达式。您可以在此处进行测试:

      正则表达式:
      Cars(?>\(?!select)\w+(?:\([^)]*\)?\s*)+\

      与vendettamit给出的答案略有不同的是,这一答案抓住了整个陈述

      编辑:那么它是如何工作的呢?

      我尝试捕获重复的部分(
      .Items()
      .Select()
      ),以便模式更易于维护/遵循

      汽车

      我把
      Cars
      放在开头,因为这样regex引擎就可以尽快知道下一组字符是否有趣。这减少了所需步骤的数量。也可以替换为
      \w+
      ,但由于整个文本中有更多字符与之匹配,因此需要执行更多步骤

      (?>

      我在这里启动一个原子组。这意味着正则表达式引擎在遵循正则表达式模式时不会回溯。这将大大提高性能,因为如果模式的一部分失败,它将不会尝试其他可能性

      \.

      逐字匹配
      字符

      (?!选择)

      负向前看-仅在不
      选择时匹配。我在regex101.com上使用了不区分大小写的修饰符,但C#也支持此功能。否则只需将其更改为
      [Ss]elect

      \w+

      至少匹配一次任何单词字符
      a-zA-Z0-9
      。这与
      where
      选择文本的一部分相匹配

      (?:

      我在这里启动了一个新的非捕获组。之所以这样做,是因为模式的下一部分是可选的(methods/lambda的
      ()
      部分)

      \(

      这只与
      字符字面上匹配

      [^)]*

      这将匹配所有内容(不包括任何内容。请参阅
      *
      ),直到遇到
      字符

      \)

      字面上匹配
      字符

      )?

      我关闭可选(请参见
      )组。请记住,这是每个方法/lambda的
      ()
      部分,但也可能是一个属性,因此
      ()
      部分必须是可选的

      \s*

      尽可能多次匹配任何空白字符(如空格、制表符和新行)

      )+

      在这里,我们结束与
      。其中(x=>x)
      文本部分匹配的组(至少一次。请参见
      +

      \
      匹配
      字符


      就这样!因此,在性能上最大的欺骗是
      汽车
      部分和
      (?>
      原子组。

      这对于正则表达式来说太难了。见鬼,即使有一个完全工作的C#解析器,这也不是一件小事!既然@dasblinkenlight提到了它。也许值得研究一下Roslyn编译器API来解析C#,并自动(在Visual Studio中)查找此类代码结构。您认为我尝试的负前瞻性是可能的吗?我正在寻找的模式不必复杂。请尝试此
      \.Items\(.*)(\W.*?)(\W.*。选择\(.+\)(\W.*))\
      …而且只需要一半的步骤就可以匹配。+1!它们都很好。我还没有弄清楚它们是如何工作的,但根据vendettamit的评论,我将您的答案切换为可接受的答案。@exportr如果您仍然感兴趣,我已经解释了正则表达式的部分。:)@测量这很好,里面肯定有我不知道的部分。