从行尾开始的 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,}(?:(?!\/\/).)*?$//;
正则表达式:\/{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;
我试图去掉我遇到的每一行末尾的注释。但是,我有兴趣保留该行,如果它在开头和结尾都被评论的话。
例如:
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,}(?:(?!\/\/).)*?$//;
正则表达式:\/{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;