Perl查找和替换(带编号的替换)进入无限循环

时间:2016-02-02 13:03:14

标签: regex perl replace find infinite-loop

今天早些时候我发布了一个类似的问题,其解决方案导致了一个新问题, - , -

好吧,故事是我希望Perl从文本中捕获注释,将它们存储在数组中,并用新编号的注释替换它们,例如,原始$ txt:

//first comment
this is a statement //second comment
//third comment
more statements //fourth comment

我想将4条评论推送到数组中,并获得新的$ txt,如:

//foo_0
this is a statement //foo_1
//foo_2
more statements //foo_3

我尝试了以下Perl:

$i=0;
$j=0;
#while ($txt =~ s/(\/\/.*?\n)/\/\/foo_$i\n/gs) {
#while ($txt =~ s/(\/\/.*?\n)/\/\/foo_$i\n/s) {
#foreach ($txt =~ s/(\/\/.*?\n)/\/\/foo_$i\n/gs) {
foreach ($txt =~ s/(\/\/.*?\n)/\/\/foo_$i\n/s) {
        if(defined $1) {
                push (@comments, $1);
                print " \$i=$i\n";
                $i++
                }
        print " \$j=$j\n";
        $j++;
        }

print "after search & replace, we have \$txt:\n";
print $txt;

foreach (0..$#comments) {
        print "\@comments[$_]= @comments[$_]";
        }

在其中,我尝试了四种口味的“while / foreach(... s /// gs)”,但它们都没有真正做到我想要的。

“foreach”声明仅对文本起作用一次;更糟糕的是,“while”语句将进入无限循环,似乎新的“// foo_xx”内容被放回到字符串中以进行进一步的搜索操作,使其成为无限循环。奇怪的是,这种看似简单的搜索和替换机制会陷入无限循环,或者有一些我不知道的明显技巧?

顺便说一句,我已经完成了帖子by highsciguy。对他来说,“只需用上面的代码替换foreach就可以了”;但对我来说,foreach不起作用,我不知道为什么。

任何人都有任何想法帮助我吗?感谢〜

2 个答案:

答案 0 :(得分:2)

我解决它的方式有点不同 - 一个循环来逐行读取文件句柄,然后抓住'所有的评论行都没有。

这样的事情:

#!/usr/bin/perl

use warnings;
use strict;

my @comments; 

#iterate stdin or filename specified on command line
while ( <> ) { 
   #replace anything starting with // with foo_nn
   #where nn is current number of comments. 
   s,//(.*),"//foo_".@comments,e && push (@comments, $1 );
   #$1 is the contents of that bracket - the string we replaced
   #stuff it into commments; 

   #print the current line (altered by the above)
   print;
}
#print the comments. 
print "Comments:\n", join "\n", @comments;

不会解决重复问题,如果您在引号或其他内容中获得//,则会中断,但确实适用于您的示例。 while基于文件句柄逐行迭代。如果你已经有一个带有文本blob的标量,那么你可以用foreach ( split ( "\n", $text ) ) {

完成同样的事情。

输出:

//foo_0
this is a statement //foo_1
//foo_2
more statements //foo_3
Comments:
first comment
second comment
third comment
fourth comment

答案 1 :(得分:1)

迭代文本的每一行,如果替换成功,请存储注释:

#!/usr/bin/perl

use strict;
use warnings;

my $txt = <<END;                        # define text
//first comment
this is a statement //second comment
//third comment
more statements //fourth comment
END

my @comments = ();
my $i = 0;
foreach (split qq(\n), $txt) {          # iterate over input lines
        if (s&(//.*)&//foo_$i&) {       # do we match?
                push @comments, $1;     # then push comment
                $i++;                   # and increase counter
                }
        print;                          # print modified row
        print qq(\n);                   # print newline
        }

print qq(\nComments:\n);
foreach (@comments) {
        print;                          # print the comment
        print qq(\n);                   # print newline
        }