Perl查找替换(带编号替换)进入死循环

Perl find-and-replace (with numbered replacement) enters infinite loop

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

嗯,故事是我希望 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 ) {
                push (@comments, );
                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)",但其中none确实达到了我想要的效果。

"foreach" 语句仅对文本起作用一次;更糟糕的是,"while" 语句将进入无限循环,似乎新的“//foo_xx”东西被放回字符串中以进行进一步的搜索操作,从而使其成为无限循环。奇怪的是,这么一个看似简单的查找和替换机制会陷入死循环,还是有什么明显的技巧我不知道?

顺便说一句,我已经完成了 post by highsciguy 。对他来说,"simply replacing while with foreach in the above code will do";但对我来说,foreach 不起作用,我不知道为什么。

有没有人能帮我解决这个问题?谢谢~

我会以不同的方式处理它 - 一个 while 循环逐行读取文件句柄,'grab' 从中读取所有注释行。

像这样:

#!/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,  );
   # 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

遍历文本的每一行,如果替换成功,则存储注释:

#!/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, ;     # 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
        }