Visual Studio正则表达式使用宏删除VB.NET代码中的所有注释和空行

时间:2012-03-01 06:16:37

标签: regex visual-studio comments replace

我试图在宏的帮助下删除文件中的所有注释和空行。现在我想出了这个删除注释的解决方案(下面描述了一些错误),但是无法删除它们之间的空行 -

Sub CleanCode()
    Dim regexComment As String = "(REM [\d\D]*?[\r\n])|(?<SL>\'[\d\D]*?[\r\n])"
    Dim regexBlank As String = "^[\s|\t]*$\n"
    Dim replace As String = ""

    Dim selection As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
    Dim editPoint As EnvDTE.EditPoint

    selection.StartOfDocument()
    selection.EndOfDocument(True)

    DTE.UndoContext.Open("Custom regex replace")
    Try
        Dim content As String = selection.Text
        Dim resultComment As String = System.Text.RegularExpressions.Regex.Replace(content, regexComment, replace)
        Dim resultBlank As String = System.Text.RegularExpressions.Regex.Replace(resultComment, regexBlank, replace)
        selection.Delete()
        selection.Collapse()
        Dim ed As EditPoint = selection.TopPoint.CreateEditPoint()
        ed.Insert(resultBlank)
    Catch ex As Exception
        DTE.StatusBar.Text = "Regex Find/Replace could not complete"
    Finally
        DTE.UndoContext.Close()
        DTE.StatusBar.Text = "Regex Find/Replace complete"
    End Try
End Sub

所以,这是运行宏之前和之后的样子。

BEFORE

Public Class Class1
    Public Sub New()
        ''asdasdas
        Dim a As String = "" ''asdasd
        ''' asd ad asd
    End Sub


    Public Sub New(ByVal strg As String)

        Dim a As String = ""

    End Sub


End Class

AFTER

Public Class Class1
    Public Sub New()
        Dim a As String = ""
    End Sub
    Public Sub New(ByVal strg As String)
        Dim a As String = ""
    End Sub
End Class

主要有两个主要问题
  • 无法删除其间的空行。
  • 如果有一段代码是这样的

Dim a as String = "Name='Soham'"

然后运行宏后,它变为

Dim a as String = "Name='"

3 个答案:

答案 0 :(得分:7)

要删除包含空格或无任何内容的行,可以使用此正则表达式:

(?m)^[ \t]*[\r\n]+

如果您指定了多线模式(^[\s|\t]*$\n),您的正则表达式(?m)会起作用,但它仍然不正确。首先,|与文字|匹配;没有必要在字符类中指定“或”。另一方面,\s匹配任何空格字符,包括TAB(\t),回车(\r)和换行符(\n),这使得它不必要地冗余且效率低下。例如,在第一个空白行(在第一个Sub结束之后),^[\s|\t]*最初将尝试匹配单词Public之前的所有内容,然后它将返回到上一行的结尾,$\n可以匹配。

但是空行除了是空的或只包含水平空格(空格或TAB)之外,还可以包含注释。我选择将这些“仅注释”行视为空行,因为它相对容易,并且它简化了在非空行中匹配注释的任务,这要困难得多。这是我的正则表达式:

^[ \t]*(?:(?:REM|')[^\r\n]*)?[\r\n]+

在使用任何前导水平空格后,如果我看到REM'表示注释,我将消耗该值及其后的所有内容,直到下一行分隔符为止。请注意,唯一需要出现的是行分隔符本身。还要注意没有结束锚$。当您明确匹配行分隔符时,永远不必使用它,在这种情况下,它会破坏正则表达式。在多行模式下,$仅在换行符(\n)之前匹配,而不是在回车符(\r)之前匹配。 (.NET风格的这种行为是incorrect,并且相当令人惊讶,因为微软长期以来一直偏好\r\n作为行分隔符。)

匹配剩余的评论是一项根本不同的任务。正如您所发现的,只是搜索REM'并不好,因为您可能会在字符串文字中找到它,而不会表示评论的开头。你要做的就是从行的开头开始,消耗并捕获任何不是注释开头或字符串文字的东西。如果您找到双引号,请继续使用字符串文字。如果您找到REM',请停止捕获并继续使用该行的其余部分。然后用刚捕获的部分替换整行 - 即评论前的所有内容。这是正则表达式:

(?mn)^(?<line>[^\r\n"R']*(("[^"]*"|(?!REM)R)[^\r\n"R']*)*)(REM|')[^\r\n]*

或者,更可读:

(?mn)             # Multiline and ExplicitCapture modes
^                 # beginning of line
(?<line>          # capture in group "line"
  [^\r\n"R']*     # any number of "safe" characters
  (
    (
      "[^"]*"     # a string literal
      |
      (?!REM)R    # 'R' if it's not the beginning of 'REM'
    )
    [^\r\n"R']*   # more "safe" characters
  )*
)                 # stop capturing
(?:REM|')         # a comment sigil
[^\r\n]*          # consume the rest of the line

替换字符串为"${line}"。其他一些说明:

  • 请注意,此正则表达式[\r\n]+结尾以使用行分隔符,就像正则表达式中的“空行”一样。
  • 它也不会以$结束,原因与之前相同。 [^\r\n]*将贪婪地消耗行分隔符之前的所有内容,因此不需要锚点。
  • 唯一需要出现的是REM';我们不打扰任何不包含评论的行匹配。
  • ExplicitCapture模式意味着我可以对我不想捕获的所有组使用(...)而不是(?:...),但命名组(?<line>...)仍然有效。
  • 尽管如此,如果VB支持多行注释,或者其字符串文字支持反斜杠转义,这个正则表达式会更糟。

我不做VB,而是here's a demo in C#

答案 1 :(得分:0)

我刚刚查看了上面的两个例子,'+{.+}$应该这样做。您可以选择使用('|'')+{.+}$,但第一个解决方案也会替换xml描述。

''' <summary>
''' Method Description
''' </summary>
''' <remarks></remarks>
Sub Main()
    ''first comment
    Dim a As String = "" 'second comment
End Sub

编辑:如果您使用('+{.+}$|^$\n),则删除a)所有注释和b)所有空行。但是,如果您有一个注释和一个结束子/函数,它会占用一行,这会导致编译器错误。

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    Sub Main()
        ''first comment
        Dim a As String = "" 'second comment

    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function asdf() As String
        Return "" ' returns nothing

    End Function

之后

Sub Main()
    Dim a As String = ""
End Sub

Public Function asdf() As String
    Return ""         
End Function

编辑:删除任何空行搜索将以下正则表达式^$\n替换为空。

答案 2 :(得分:0)

首先使用此正则表达式删除注释

&#39;。+ \ S *(\ W | \ W)+

&#39; + - 一个或多个&#39;每篇评论的开头。

\ s * - 如果评论后有空格。

(\ W | \ w)。+ - 除了行终止符之外的所有内容。

然后使用Alan Moore先生提供的正则表达式删除留下的空白行。