【发布时间】:2019-08-14 13:07:45
【问题描述】:
为什么这两个正则表达式在 Notepad++ 中会产生不同的结果?
-
//.*?\n|//.*$|\s+|.(2 匹配 → screenshot) -
//.*?(?:\n|$)|\s+|.(3 匹配 → screenshot)
背景
我正在用 Perl 为 Delphi 编写一个原始词法分析器。目的是提取词(标识符和关键字),因此不需要正确识别各种标记。
它的核心是下面的正则表达式:
\{[^}]*\}|\(\*([^*]|\*[^\\])*?\*\)|[A-Za-z_]\w*|\d+|//.*?$|'([^']|'')*?'|\s+|.
我偶然发现行尾没有被行 cmets 消耗。所以我很好奇我是否可以修改正则表达式,以便完全由行 cmets 组成的两个连续行被计为 2 个“令牌”。
// first line
// last line
我用//.*?\n 替换了//.*?$,但是使用这个正则表达式,直接放置在EOF(没有换行符)之前的行注释将不匹配,而是分为/、/ 等等。所以我寻找正确的方式来正确表达交替。我发现两个在 Notepad++ 和 winGrep 中表现不同但在 Perl 中相同的正则表达式:
实际差异已在介绍性问题中显示:
\{[^}]*\}|\(\*([^*]|\*[^\\])*?\*\)|[A-Za-z_]\w*|\d+|//.*?\n|//.*?$|'([^']|'')*?'|\s+|.(上述示例源中有 2 个匹配项)\{[^}]*\}|\(\*([^*]|\*[^\\])*?\*\)|[A-Za-z_]\w*|\d+|//.*?(?:\n|$)|'([^']|'')*?'|\s+|.(上述示例源中有 3 个匹配项)
可以在 Notepad++(7.7.1 32 位)和 grepWin(1.9.2 64 位)中观察到。在 Perl 中,我将正则表达式放在 m@( 和 )@mg 之间,两者都有 2 个匹配项。
【问题讨论】:
-
参见。 regex101.com/r/Orqud1/1 和 regex101.com/r/Orqud1/2:它们与您的示例字符串匹配相同。
-
//.*?\n|//.*?$将运行\n部分,失败然后运行$部分,因为它找不到换行符,但//.*?(?:\n|$)不会。这就是行为的差异(afaik),但我找不到结果的差异。s标志将使.匹配\n在这种情况下不会改变结果。 -
@Wolf
s是一个单行修饰符,您不应将其与//.*$之类的模式一起使用,因为您只想匹配换行符以外的字符。 -
好的,
//.*?\n|//.*?$和//.*?(?:\n|$)显示 2 个匹配项。我怀疑后面的\s+与\n之前的CR、回车符匹配。 -
既然您使用的是
. Matches newline,我可以建议\/\/[^\r\n]*吗? regex101.com/r/VEc6Dl/1
标签: regex notepad++ newline regex-alternation