从行尾开始的 perl 模式匹配

perl pattern matching from end of line

我试图去掉我遇到的每一行末尾的注释。但是,我有兴趣保留该行,如果它在开头和结尾都被评论的话。

例如:

output port_a; // comments remove this port

如果我使用这个正则表达式 $line =~ s/\/{2,}.*?$//;,注释将被正确删除,只产生我想用于进一步处理的模式,即:

output port_a;

但是,也有可能一行可以在开头注释:

// output port_a; // comments remove this port

在这种情况下,我想保留行首的注释,但删除行尾的注释。

// output port_a; 

使用相同的正则表达式 $line =~ s/\/{2,}.*?$//; 删除所有内容!

我试过使用 s/\/{2,}[^\/]+$//g 但这并没有去掉其中有斜杠的注释,这是不正确的:

// output port_a; // comments read/write    

以下工作,使用 @ 作为正则表达式分隔符而不是 / 以避免 / 之前的反斜杠并且更清晰

s@//([^/]|/([^/]|$))*$@@

它是如何工作的。 在 // 之后:我们可以找到

  • 或者 [^/](除 / 之外的任何字符)
  • / 后跟 [^/]$ 行尾锚点

使用钢化点,

$line =~ s/\/{2,}(?:(?!\/\/).)*?$//;

Regex101 Demo

正则表达式:\/{2,}(?:(?!\/\/).)*?$

  • \/{2,} 匹配 2 个或更多斜线(代表注释的开始)
  • (?:(?!\/\/).)*? 代表一个调和点(这意味着除了前面有 // 的字符之外的任何字符)。这是使用负前瞻指定的 (?!\/\/).
  • $结尾锚点

希望对您有所帮助!

允许在开头使用可选的 /,如果有则删除尾随注释

s|^\s*/?.+?\K//.*||g;

需要 + 量词而不是 * 以便不匹配带有唯一注释的行。

\K is a form of lookbehind零宽度断言,它前面的模式确实存在(它不消耗任何东西)。它还会丢弃之前的所有匹配项,因此我们不必捕获它们并将它们放回原处。这也允许 \K 处理可变长度模式。

使用显示的示例进行测试

use warnings;
use strict;
use feature 'say';

my @tests = (
    'output port_a; // comments remove this port',
    '// output port_a; // comments remove this port',
    '// output port_a; // comments read/write'
);

for (@tests)
{ 
    s|^\s*/?.+?\K//.*||gx;
    say;
}

输出

output port_a; 
// output port_a;
// output port_a;

这将删除行中的 last 注释。清晰多了

s|.*\K//.*||

这是一个演示程序

use strict;
use warnings 'all';

while ( <DATA> ) {

    print "$.\n";

    print;

    s|.*\K//.*||;
    print;

    print "\n";
}

__DATA__
output port_a; // comments remove this port
output port_a;
// output port_a; // comments remove this port
// output port_a; 

产出

1
output port_a; // comments remove this port
output port_a; 

2
output port_a;
output port_a;

3
// output port_a; // comments remove this port
// output port_a; 

4
// output port_a;