Regex 如何在Perl中进行条件贪婪匹配?

Regex 如何在Perl中进行条件贪婪匹配?,regex,perl,conditional,match,greedy,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解析代码文本并识别某些内容,例如代码:

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
使用严格;
使用警告;
$/=未定义;
而(){

s/(\w+)(\s*这比您想象的要复杂得多,如果不为您试图处理的语言编写解析器,就不可能正确地完成。但是,如果您的示例始终是该语言的有限子集,您可能会很幸运

我能看到的最好的方法是使用
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
使用严格;
使用警告;
我的$data=do{
本地$/;
;
};
我的@split=split/(\((?>[^()]|(?1))*\)/x,$data;
对于(@split){
下一个if/[()]/;

s/^\s*\w+\K(?=\s*检查并编写该语言的语法分析器。请参见或.Katyusza,您可以删除
if\s*
,它将是一个语法分析器。解析Verilog并不是一件小事:@Katyusza:如果您这样做,那么您应该意识到您正在为自己设置一个巨大的任务。但是请注意您可能使用的模块。您注定要失败如果你从简单开始regexes@katyusza它类似于
s/(\((?>[^()]+|(?1))*\)(*跳过)(*F)|^\s*\w+\K(?=\s*@BobbleBobble:我已经做了我认为你的意思是的更改,但是这些更改很小,而且我确信它们不会对程序的性能产生影响。除非数据量很大,否则这将是磁盘绑定的。我真的不知道该怎么做,而不是在一行的开头锚定:整个事情真的需要锚定在后面语句边界,可以是
begin
的分号,也可以是其他的,如果它们在引号或注释中,则必须忽略它们。这真的不是一次性的工作regex@Borodin我不明白为什么要使用
(*SKIP)(*F)
进行拆分/合并,这对于此类情况来说很方便,而且不“神奇”。它会丢弃您用作拆分序列的部分。如果锚定到行首或使用分号取决于输入。我更喜欢分号变体,但您的也可以。为了提高性能,我会在
[^()]中添加
+
量词
的交替性较低:vs或介于两者之间。详细的回答。@bobblebubble:正如我所说,没有正则表达式递归,这个问题是无法解决的。我判断
\K
似乎在一个普通Perl程序员的词汇表中,而很少有人考虑回溯或了解star命令。如果你认为我的cr它是错误的,那么你复制它肯定也是错误的吗?