今天早些时候我发布了一个类似的问题,其解决方案导致了一个新问题, - , -
好吧,故事是我希望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不起作用,我不知道为什么。任何人都有任何想法帮助我吗?感谢〜
答案 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
}