要删除包含空格或不包含任何内容的行,可以使用以下正则表达式:
(?m)^[ \t]*[\r\n]+
你的正则表达式,^[\s|\t]*$\n
如果您指定多行模式((?m)
),但它仍然是不正确的。一方面,|
匹配文字|
;无需在字符类中指定“或”。为了另一个,\s
匹配任何空白字符,包括 TAB (\t
), 回车符 (\r
) 和换行符 (\n
),使其不必要地冗余且效率低下。例如,在第一个空行处(在第一个空行结束之后)Sub
), the ^[\s|\t]*
最初会尝试匹配该单词之前的所有内容Public
,然后它将退回到上一行的末尾,其中$\n
可以匹配。
但是,空行除了为空或仅包含水平空白(空格或制表符)之外,还可能包含注释。我选择将这些“仅注释”行视为空行,因为它相对容易做到,并且它简化了匹配非空行中的注释的任务,而这要困难得多。这是我的正则表达式:
^[ \t]*(?:(?:REM|')[^\r\n]*)?[\r\n]+
在消耗任何前导水平空白后,如果我看到REM
or '
表示注释,我会使用它及其后面的所有内容,直到下一个行分隔符。请注意,唯一需要出现的是行分隔符本身。另请注意末端锚点的缺失,$
。当您显式匹配行分隔符时,没有必要使用它,在这种情况下,它会破坏正则表达式。在多行模式下,$
仅在换行符之前匹配 (\n
),不在回车符之前 (\r
)。 (.NET 风格的这种行为是不正确考虑到微软长期以来对\r\n
作为行分隔符。)
匹配剩余的评论是一项根本不同的任务。正如您所发现的,只需搜索REM
or '
不好,因为您可能会在字符串文字中找到它,它并不表示注释的开始。你要做的就是从该行的开头开始,消耗并捕捉任何不是注释或字符串开头的内容。如果找到双引号,请继续使用字符串文字。如果你找到一个REM
or '
,停止捕获并继续消耗该行的其余部分。然后,您仅用捕获的部分(即注释之前的所有内容)替换整行。这是正则表达式:
(?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}"
。其他一些注意事项:
- 请注意,这个正则表达式确实not结束于
[\r\n]+
消耗行分隔符,就像“空行”正则表达式一样。
- 它并没有结束于
$
要么,出于与之前相同的原因。这[^\r\n]*
将贪婪地消耗行分隔符之前的所有内容,因此不需要锚点。
- 唯一需要出现的是
REM
or '
;我们不会去匹配任何不包含注释的行。
- ExplicitCapture 模式意味着我可以使用
(...)
代替(?:...)
对于我不想捕获的所有组,但指定的组,(?<line>...)
,仍然有效。
- 尽管很粗糙,但如果 VB 支持多行注释,或其字符串文字支持反斜杠转义,则该正则表达式会变得更糟。
我不会VB,但是这是一个 C# 演示.