kat*_*sza 5 regex perl conditional match greedy
我希望Perl解析代码文本并识别某些东西,例如代码:
use strict;
use warnings;
$/ = undef;
while (<DATA>) {
s/(\w+)(\s*<=.*?;)/$1_yes$2/gs;
print;
}
__DATA__
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
d1 <= 0; //perl_comment_4
//perl_comment_5
d2 <= 1 //perl_comment_6
+ 2;
end
else if( d3 <= d4 && ( d5 <= 3 ) ) begin
d6 <= d7 +
(d8 <= d9 ? 1 : 0);
//perl_comment_7
d10 <= d11 <=
d12
+ d13
<= d14 ? 1 : 0;
end
Run Code Online (Sandbox Code Playgroud)
匹配目标是满足以下所有条件的:
(1)从组合开始word\s*<=.这里\s*可能有0个或更多空格,换行符,制表符.
(2)上述"组合"应该是任何一对(和).
(3)如果连续出现多个"组合",则以第一个作为开头.(左边界的"贪婪"匹配)
(4);以(1)中提到的"组合"之后的第一个结束.
有可能是word\s*<=和;代码中的注释(有可能是在评论任何东西); 这使事情变得更加复杂.为了让生活更轻松,我已经预处理了文本,扫描了评论并用类似的东西替换它们//perl_comment_6.(这个解决方案看起来相当麻烦和愚蠢.任何更智能,更优雅的解决方案?)
我想做什么:
对于所有匹配word\s*<=,替换word为word_yes.对于示例代码,d1,d2,d6和d10应分别替换为d1_yes,d2_yes,d6_yes和d10_yes,并且文本的所有其他部分应保持不变.
在我使用的当前代码中s/(\w+)(\s*<=.*?;)/$1_yes$2/gs;,它正确识别d1,d2和d10,但无法识别d6并错误地识别d3.
有什么建议?提前谢谢〜
这可能是您想象的更复杂,如果没有为您尝试处理的语言编写解析器,则无法正常执行.但是,如果您的样本始终是该语言的有限子集,您可能会很幸运
我可以看到这样做的最好方法是使用split从要进行替换的"顶级"部分中分离括号中字符串的所有子部分.然后可以对相关部件进行更改,并将拆分部分连接在一起
即使这依赖于具有正确平衡括号的代码,并且出现在字符串或注释中的奇数打开或关闭括号将抛出该过程.split必须使用递归中的正则表达式,以便可以匹配嵌套的括号,并使其成为捕获正则表达式,使得split返回字符串的所有部分而不仅仅是匹配之间的部分
这段代码会按照你的要求进行,但请注意,正如我所描述的那样,它非常脆弱
use strict;
use warnings;
my $data = do {
local $/;
<DATA>;
};
my @split = split / ( \( (?> [^()] | (?1) )* \) ) /x, $data;
for ( @split ) {
next if /[()]/;
s/ ^ \s* \w+ \K (?= \s* <= ) /_yes/xgm;
}
print join '', @split;
__DATA__
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
d1 <= 0; //perl_comment_4
//perl_comment_5
d2 <= 1 //perl_comment_6
+ 2;
end
else if( d3 <= d4 && ( d5 <= 3 ) ) begin
d6 <= d7 +
(d8 <= d9 ? 1 : 0);
//perl_comment_7
d10 <= d11 <=
d12
+ d13
<= d14 ? 1 : 0;
end
Run Code Online (Sandbox Code Playgroud)
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
d1_yes <= 0; //perl_comment_4
//perl_comment_5
d2_yes <= 1 //perl_comment_6
+ 2;
end
else if( d3 <= d4 && ( d5 <= 3 ) ) begin
d6_yes <= d7 +
(d8 <= d9 ? 1 : 0);
//perl_comment_7
d10_yes <= d11 <=
d12
+ d13
<= d14 ? 1 : 0;
end
Run Code Online (Sandbox Code Playgroud)