【问题标题】:Extract Enums with brackets in comments?在评论中提取带括号的枚举?
【发布时间】:2019-06-16 22:32:56
【问题描述】:

我要提取的枚举如下:

...
other code 
...
enum A
{
  a,
  b=2,
  c=3,
  d//{x}
}
...
More Enums like the above.
...

首先,我尝试使用带有正则表达式的选项Singleline
enum\s*\w+\s*{.*?\}

但是,由于 cmets 有括号。正则表达式不起作用。运行到cmets中的括号会停止。

所以我尝试在 cmets 之后排除括号。根据我到目前为止搜索的内容,似乎我需要对分组构造 Multiline 进行负面展望。

然后我尝试在没有 cmets 的情况下解析括号。
子步骤是在 cmets 之后找到括号: (?m:^.*?//.*?}.*?$).

但是,即使在内联多行模式下,. 似乎仍然匹配任何字符,包括换行符。

然后我首先尝试使用多行。由于主要问题是 cmets 中的括号。我试过:
(?!//.*)} 消极的展望并没有像我预期的那样工作。

这里有一个csharp-regex-test-link 供你测试。

总而言之,我需要从 csharp 源代码文件中解析枚举。

对我来说主要问题是 cmets 中的括号。

编辑: 澄清

1.cmets 中的括号是成对的。例如:

xxx=xxx; //{xx} 

2.cmets只有//的形式

3.我不能依赖缩进。

【问题讨论】:

  • 不确定.NET 是否支持递归,但如果支持,您可以使用regex101.com/r/AAuHg2/1 如果不支持,您可以使用平衡组构造 - docs.microsoft.com/en-us/dotnet/standard/base-types/…
  • 如果您的代码缩进良好({ 在各自的行中开始和结束),您可以利用它:(?ms)enum\s*\w+\s*^{.*?^}\r?$。您不能依赖平衡组,因为 cmets 中的 {} 不必是平衡的。如果递归存在于 .NET 正则表达式中,它不会有帮助。
  • 用Regex解析源代码的尝试是不是和parsing HTML with Regex一样的错误方法?
  • @UweKeim 可能是对的。但是,这取决于。我使用 roslyn 来解析 c# 代码。但是,在生产中存在一些限制。使用正确的方法可能不是正确的解决方案。但感谢您的建议。

标签: c# regex negative-lookahead


【解决方案1】:

你可以使用

@"\benum\s*\w+\s*{(?>[^{}]+|(?<o>){|(?<-o>)})*(?(o)(?!)|)}"

regex demo

详情

  • \benum - 一个完整的词enum
  • \s* - 0+ 个空格
  • \w+ - 1+ 字字符
  • \s* - 0+ 个空格
  • { - 一个 { 字符
  • (?&gt;[^{}]+|(?&lt;o&gt;){|(?&lt;-o&gt;)})* - 除了{} 之外的 1+ 个字符,或者带有一个空字符串的 { 被压入 Group o 堆栈,或者 } 带有一个从 Group o 堆栈中弹出的值
  • (?(o)(?!)|) - 一个条件 yes-no 构造,如果 Group o 仍有任何项目留在堆栈中,则匹配失败并使正则表达式引擎回溯到当前位置
  • } - } 字符。

【讨论】:

  • 关于条件是-否,为什么要加|(?(o)(?!))(?(o)(?!)|) 有什么区别?
  • @AlexWei 在平衡构造中通常不使用|,但为了与正则表达式语法保持一致,欢迎使用空无部分模式。在其他情况下,不遗漏任何部分可能会导致意外结果。
【解决方案2】:

我认为不可能使用单个正则表达式来完成您的任务。如果你有一个看起来像这样的字符串怎么办

var notEnum = "enum A {a, b, c}";

不过,您只需几遍就可以捕获您的枚举。看看这个算法

  1. 清除字符串内容
  2. 删除单行 cmets
  3. 滴木莲碱
  4. 使用你原来的正则表达式

例子:

var code = ...

var stringLiterals = new Regex("\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"", RegexOptions.Compiled);
var multilineComments = new Regex("/\\*.*?\\*/", RegexOptions.Compiled | RegexOptions.Singleline);
var singlelineComments = new Regex("//.*$", RegexOptions.Compiled | RegexOptions.Multiline);
var @enum = new Regex("enum\\s*\\w+\\s*{.*?}", RegexOptions.Compiled | RegexOptions.Singleline);

code = stringLiterals.Replace(code, m => "\"\"");
code = multilineComments.Replace(code, m => "");
code = singlelineComments.Replace(code, m => "");

var enums = @enum.Matches(code).Cast<Match>().ToArray();

foreach (var match in enums)
    Console.WriteLine(match.Value);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 2016-09-16
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    相关资源
    最近更新 更多