我试图在宏的帮助下删除文件中的所有注释和空行。现在我想出了这个删除注释的解决方案(下面描述了一些错误),但是无法删除它们之间的空行 -
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='"
答案 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
或'
;我们不打扰任何不包含评论的行匹配。(...)
而不是(?:...)
,但命名组(?<line>...)
仍然有效。我不做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先生提供的正则表达式删除留下的空白行。