【问题标题】:Visual Studio regex to remove all comments and blank lines in VB.NET code using a macro使用宏删除 VB.NET 代码中的所有注释和空行的 Visual Studio 正则表达式
【发布时间】:2012-03-19 16:05:09
【问题描述】:

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

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

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

之前

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

之后

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='"

【问题讨论】:

    标签: regex visual-studio comments replace


    【解决方案1】:

    我刚刚检查了上面的两个示例,'+{.+}$ 应该可以。或者,您可以使用('|'')+{.+}$,但第一个解决方案也替换了 xml-descriptions )。

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

    编辑:如果您使用('+{.+}$|^$\n),它会删除 a) 所有 cmets 和 b) 所有空行。但是,如果您有注释和后面的 End Sub/Function,它将占用一行,从而导致编译器错误。

    之前

        ''' <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 替换为空。

    【讨论】:

    • 无论如何,Alex 我已经完成了第一部分,现在我想删除它留下的空白行或代码文档中的任何其他空白行。帮我解决这个问题。
    • 查看我的最新编辑 - 你也可以将它与我已经写过的第一个正则表达式结合起来。
    • 你能告诉我这个正则表达式有什么问题吗 - ^[\s|\t]*$\n?我不知何故无法弄清楚这里出了什么问题。
    • 您的正则表达式适用于我删除所有空行。您确定您在搜索替换窗口中启用了“使用正则表达式”吗?
    • 你是对的,正则表达式在普通的 VS2010 查找和替换窗口中工作,但是,正如你所看到的,我正在使用 System.Text.RegularExpressions.Regex 类编写我自己的自定义宏,这就是正则表达式行不通。注释替换也有一点问题,比如源代码中有一行 - b.RowFilter = "Name='Soham'" 然后在运行宏后变成这样 - b.RowFilter = "Name="
    【解决方案2】:

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

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

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

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

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

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

    匹配剩余的 cmets 是一项根本不同的任务。正如您所发现的,简单地搜索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 模式意味着我可以对我不想捕获的所有组使用(...) 而不是(?:...),但命名组(?&lt;line&gt;...) 仍然有效。
    • 虽然很粗糙,但如果 VB 支持多行 cmets,或者如果它的字符串文字支持反斜杠转义,这个正则表达式会更糟。

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

    【讨论】:

    • 你只是一个正则表达式大师。奇迹般有效。太好了,我必须说。我刚刚将我的 50 分奖励给了应得的人。
    • @Alan:我想要 c# cmets 和空白行的相同解决方案。我使用下面的正则表达式从文本中删除评论。但是如何删除空行:var blockComments = @"/*(.*?)*/"; var lineComments = @"//(.*?)$"; b> regex = new Regex(lineComments, RegexOptions.Multiline); functionText = regex.Replace(functionText, String.Empty);正则表达式 = 新正则表达式(blockComments,RegexOptions.Singleline); functionText = regex.Replace(functionText, String.Empty);
    【解决方案3】:

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

    '+\s*(\W|\w).+

    '+ - 每条评论的开头有一个或多个'。

    \s* - 如果注释后有空格。

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

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

    【讨论】:

      猜你喜欢
      • 2016-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      • 2011-08-17
      • 2011-01-28
      相关资源
      最近更新 更多