为什么我的正则表达式也抓取 EOLN?

Why does my regular expression grab the EOLN as well?

我正在尝试编写一个批处理文件来自动批量编辑某些 Pascal 源代码。我的源文件偶尔会有这样一行:

     //{## identifier} Inc (Index) ; { a comment }    // another comment

我想将它们全部更改为:

     {$ifdef identifier} Inc (Index) ; { a comment }    // another comment {$endif}

下面是我正在使用的测试批处理文件。

:: File TestRXRepl.bat
:: ===================     

@echo     //{##   identifier} Inc (Index) ; { a comment }    // another comment >t.pas
@set "FindRegExp=(\ *)\/\/\{\#\#\ *([a-z,0-9,_]+)\}(\ *)(.*)"
@set "ReplRegExp={$ifdef } {$endif}"

rxrepl --file t.pas --output t.out --search "%FindRegExp%" --replace "%ReplRegExp%"
@type t.pas
@type t.out

正则表达式应该是:

除行尾处理外一切正常。第 4 组应该捕获从源行开始到行尾的所有内容,但它似乎 include 行尾,结果是 {endif}被写入下一行,即我得到:

{$ifdef identifier} Inc (Index) ; { a comment }    // another comment
{$endif}

而不是:

{$ifdef identifier} Inc (Index) ; { a comment }    // another comment {$endif}

我使用的工具是RXRepl。它有一个选项 --eol,听起来可能很有用,但我无法通过使用它来改变行为。

(备注)

欢迎提出让它更优雅的建议,以及让它正常工作的建议。

问题似乎是您的 . 正在匹配换行符,这意味着 PCRE2_DOTALL 选项有效。 (我不知道为什么会这样,可能 rxrepl 总是默认设置该选项。)

一种可能的解决方法是在正则表达式匹配中以 (.*\S) 结束第 4 组,使用 \S character type 匹配任何不是空格的字符,并将排除换行符。

但可能解决此问题的最佳方法是使用 the \N sequence,手册中将其描述为:

The \N escape sequence has the same meaning as the "." metacharacter when PCRE2_DOTALL is not set, but setting PCRE2_DOTALL does not change the meaning of \N.

所以只要在你的匹配中对第 4 组使用 (\N*) 就会匹配它当前匹配的所有内容,除了尾随的换行符。

在您的脚本中,只需更新此行:

@set "FindRegExp=(\ *)\/\/\{\#\#\ *([a-z,0-9,_]+)\}(\ *)(\N*)"