【问题标题】:Match single-line comments via regex in Notepad++在 Notepad++ 中通过正则表达式匹配单行注释
【发布时间】:2019-08-14 13:07:45
【问题描述】:

为什么这两个正则表达式在 Notepad++ 中会产生不同的结果?

  1. //.*?\n|//.*$|\s+|.(2 匹配 → screenshot
  2. //.*?(?:\n|$)|\s+|.(3 匹配 → screenshot

背景

我正在用 Perl 为 Delphi 编写一个原始词法分析器。目的是提取词(标识符和关键字),因此不需要正确识别各种标记。

它的核心是下面的正则表达式:

\{[^}]*\}|\(\*([^*]|\*[^\\])*?\*\)|[A-Za-z_]\w*|\d+|//.*?$|'([^']|'')*?'|\s+|.

我偶然发现行尾没有被行 cmets 消耗。所以我很好奇我是否可以修改正则表达式,以便完全由行 cmets 组成的两个连续行被计为 2 个“令牌”。

// first line
// last line

我用//.*?\n 替换了//.*?$,但是使用这个正则表达式,直接放置在EOF(没有换行符)之前的行注释将不匹配,而是分为// 等等。所以我寻找正确的方式来正确表达交替。我发现两个在 Notepad++ 和 winGrep 中表现不同但在 Perl 中相同的正则表达式:

实际差异已在介绍性问题中显示:

  1. \{[^}]*\}|\(\*([^*]|\*[^\\])*?\*\)|[A-Za-z_]\w*|\d+|//.*?\n|//.*?$|'([^']|'')*?'|\s+|.(上述示例源中有 2 个匹配项)

  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/1regex101.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


【解决方案1】:

Windows 换行剖析

观察到的 Perl 和外部工具之间的差异是由 \r\n\n 之间的差异造成的。如果您在 Perl 中读取文本文件,则换行符(序列)将被转换为 \n,即 one 字符,因此 \n 将此字符匹配为换行符。

在记事本和 grepWin 中,不执行此翻译。所以//.*?(?:\n|$) 从不消耗换行序列,而是在正则表达式引擎匹配$ 的开头(正好在e\r 之间)停止,\r 保留在输入中; \s+ 然后匹配整个换行序列 (\r\n)。

另一方面,//.*?\n\r. 匹配,然后与\n 匹配。

如果您将模式中的换行符更改为 \r\n 以供外部工具使用,则两种选择都会给出 两个 匹配项:

  • //.*?\r\n|//.*$|\s+|.

  • //.*?(?:\r\n|$)|\s+|.

【讨论】:

    猜你喜欢
    • 2012-10-26
    • 2013-04-20
    • 1970-01-01
    • 2011-10-29
    • 2010-11-14
    • 2012-01-14
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多