这是丑陋的正则表达式模式。我相信它会运作良好。我已经用我能想到的每一个病态例子都试过了,包括包含语法错误的行。例如,一个带引号的字符串有太多引号,或者太少,或者有一个双引号,因此 not 被转义。并且在 cmets 中使用带引号的字符串,众所周知,当我想提醒自己替代方案时会这样做。
唯一会出错的情况是,如果在 看似 引用的字符串中有双斜杠,并且该字符串格式不正确,并且双斜杠在正确引用的部分之外合法地结束。从语法上讲,这使它成为一个有效的注释,即使不是程序员的意图。所以,从程序员的角度来看,这是错误的,但按照规则,它确实是一个注释。意思是,该模式似乎只会跳闸。
使用该模式时,将返回行的非注释部分。该模式中有一个换行符\n,以允许将其应用于整个文件。如果您的系统以其他方式解释换行符,您可能需要修改它,例如\r 或\r\n。要在单行模式下使用它,您可以选择删除它。它在单行版本的第 17 和 18 个字符处,在多行版本的第 5 行、第 6 和第 7 个打印字符上。但是,您可以放心地将它留在那里,因为在单行模式下它没有任何区别,而在多行模式下,它将为空白的代码行返回一个换行符,或者在第一列开始有注释。如果您将结果写入新文件,这将使原始版本和简化版本中的行号保持相同。便于比较。
此模式的一个主要警告:它使用在正则表达式引擎中具有不同级别支持的分组构造。我相信在这里使用,环顾四周,只有 .NET 和 PCRE 引擎才能接受 YMMV。它是第三类:(?(_condition_)_then_|_else_)。 _condition_ 模式被视为零宽度断言。如果模式匹配,则在尝试的匹配中使用_then_ 模式,否则使用_else_ 模式。如果没有这种结构,该模式会变得非常长,并且在我的一些病态测试用例中仍然失败。
这里展示的模式是正则表达式引擎需要看到的。我不是 C# 程序员,所以我不知道转义引用字符串的所有细微差别。将此模式放入您的代码中,以便正则表达式引擎正确看到所有反斜杠和引号仍然取决于您。或许 C# 有相当于 Perl 的 heredoc 语法。
这是要使用的单线模式:
^((?:(?:(?:[^"'/\n]|/(?!/))*)(?("(?=(?:\\\\|\\"|[^"])*"))(?:"(?:\\\\|\\"|[^"])*")|(?('(?=(?:\\\\|\\'|[^'])*'))(?:'(?:\\\\|\\'|[^'])*')|(?(/)|.))))*)
如果你想使用忽略模式空白选项,你可以使用这个版本:
(?x) # Turn on the ignore white space option
^( # Start the only capturing group
(?: # A non-capturing group to allow for repeating the logic
(?: # Capture either of the two options below
[^"'/\n] # Capture everything not a single quote, double quote, a slash, or a newline
| # OR
/(?!/) # Capture a slash not followed by a slash [slash an negative look-ahead slash]
)* # As many times as possible, even if none
(?(" # Start a conditional match for double-quoted strings
(?=(?:\\\\|\\"|[^"])*") # Followed by a properly closed double-quoted string
) # Then
(?:"(?:\\\\|\\"|[^"])*") # Capture the whole double-quoted string
| # Otherwise
(?(' # Start a conditional match for single-quoted strings
(?=(?:\\\\|\\'|[^'])*') # Followed by a properly closed single-quoted string
) # Then
(?:'(?:\\\\|\\'|[^'])*') # Capture the whole double-quoted string
| # Otherwise
(?([^/]) # If next character is not a slash
.) # Capture that character, it is either a single quote, or a double quote not part of a properly closed
) # end the conditional match for single-quoted strings
) # End the conditional match for double-quoted strings
)* # Close the repeating non-capturing group, capturing as many times as possible, even if none
) # Close the only capturing group
这允许您的代码解释这个怪物,这样当其他人看到它时,或者在几个月后您必须自己处理它时,没有 WTF 时刻。我认为 cmets 解释得很好,但您可以随意更改它们。
如上所述,条件匹配分组的支持有限。它会失败的一个地方是您在之前的评论中链接到的网站。由于您使用的是 C#,因此我选择在可以处理这些构造的 .NET Regex Tester 中进行测试。它也包括一个很好的参考。鉴于侧面的正确选择,您可以测试上述任一版本,并对其进行试验。考虑到它的复杂性,我建议在某个地方针对您文件中的数据以及您可以想到的任何边缘案例和病理测试对其进行测试。
为了弥补这个小模式,有一个更大的模式用于测试电子邮件地址,它是 78 列 x 81 行,还有几十个字符。 (我不建议使用或任何其他正则表达式来测试电子邮件地址。该工作的工具错误。)如果你想吓唬自己,请在ex-parrot 网站上查看它.我和那个无关!!