2013-03-20 6 views
0

У меня есть текстовый файл со смешанным NC-кодом и C# -Code. C# -Code начинается с «< #» и заканчивается на «#>». Теперь мне нужно одно выражение регулярных выражений, чтобы найти все NC-комментарии. Одна из проблем заключается в том, что NC-Комментарии начинаются с ";" поэтому у меня возникли некоторые проблемы, чтобы отличить NC-Comment от «;» C# -Code.Regex Match NC-Комментарии в строке со смешанным C# -кодом

Можно ли достичь этого только одним регулярным выражением?

; 1. NC-Comment 
FUNCT_A; 
FUNCT_B; 

<# // C#-Code 
int temp = 42; 
string var = "hello"; // C#-Comment 
#> 

FUNCT_C ; 2. Comment 

<# // C#-Code 
for(int i = 0; i <10; i++) 
{ 
    Console.WriteLine(i.ToString()); 
} 
#> 

; 3. Comment 
FUNCT_D; 

Результатом регулярного выражения должно быть {1. NC-Комментарий, 2. Комментарий, 3. Комментарий}

Я играл Arround со следующими регулярными выражениями:

1.) (;(.*?)\r?\n) --> Finds all NC-Comments but also C#-Code as comment 
2.) (#>.*?<#)|(#>.*) --> Finds all NC-Code except the first NC-Code fragment 
3.) #>.+?(?=<#) --> Finds all NC-Code except the first and last NC-Code fragment 

Одним из решений может быть, чтобы подтолкнуть каждый «< #» в стек и поп каждый " #> "из этого стека. Поэтому, если стек пуст, тогда текущая строка - NC-Code. Затем я должен выяснить, является ли эта строка NC-Comment.

+0

Зачем использовать сложное медленное регулярное выражение, когда вы можете делать то же самое проще и быстрее без регулярного выражения? –

+0

Это не так просто. Что делать, если сам код C# содержит комментарий? Что, если у вас есть '<#' or '#>' в комментариях C#? –

+0

И как бы вы достигли этого без регулярного выражения? – user1579585

ответ

1

Я предпочитаю делать это без регулярных выражений:

public static List<string> GetNCComments(Stream stream) 
{ 
    using (StreamReader sr = new StreamReader(stream)) 
    { 
     List<string> result = new List<string>(); 
     bool inCS = false; // are we in C# code? 
     int c; 
     while ((c = sr.Read()) != -1) 
     { 
      if (inCS) 
      { 
       switch ((char)c) 
       { 
        case '#': 
         if (sr.Peek() == '>') // end of C# block 
         { 
          sr.Read(); 
          inCS = false; 
         } 
         break; 
        case '/': 
         if (sr.Peek() == '/') // a C# comment 
          sr.ReadLine(); // skip the whole comment 
         break; 
       } 
      } 
      else 
      { 
       switch ((char)c) 
       { 
        case '<': 
         if (sr.Peek() == '#') // start of C# block 
         { 
          sr.Read(); 
          inCS = true; 
         } 
         break; 
        case ';': // NC comment 
         string comment = sr.ReadLine(); 
         if (!string.IsNullOrEmpty(comment)) 
          result.Add(comment); 
         break; 
       } 
      } 
     } 
     return result; 
    } 
} 

Использование:

var comments = GetNCComments(new FileStream(filePath, FileMode.Open, FileAccess.Read)); 

код прост и сам объяснительный. Это также обрабатывает комментарии C#, но не строки C#. Я имею в виду, что он работает правильно, если у вас есть #> в комментарии C#. Но не работает, если у вас есть одна и та же строка C# (неправильно рассматривается как конец блока C#). Обращение с этим случаем также легко.