我在代码中遇到了一点问题,需要一些帮助。
我有一个类似如下的文件:
some lines
some lines
LABEL:
NOP ABC some text - line 1
NOP ABC some text - line 2
NOP ABC some text - line 3
NOP ABC some text - line 4
NOP ABC some text - line 5
NOP ABC some text - line 6
NOP ABC some text - line 7
NOP ABC some text - line 8
NOP ABC some text - line 9
NOP ABC some text - line 10
NOP ABC some text - line 11现在,我的要求是,一旦LABEL:匹配,我必须跳过下一行(第1行),并修改接下来的两行,即第2行和第3行,用DEF ABC替换ABC。然后跳过接下来的2行,4和5,并用同样的方法修改接下来的2行,6和7。然后再次跳过接下来的2行,8和9,并修改下面的2行,10和11等等。
我想不出该如何做到这一点。以下是我的代码的相关部分:
while (<>) {
my $cur_line = $_;
my $ctv_line = "";
if ($cur_line =~ /^LABEL/) {
print "$cur_line";
my $next_line = <>;
print "$next_line\n";
for ($i = 0; $i < 2; $i++) {
if ($next_line =~ s/NOP\s+ABC/NOP DEF ABC/) {
$ctv_line = $next_line;
print "$ctv_line";
}
}
print "$next_line";
print "next_line";
for ($i = 0; $i < 2; $i++) {
if ($next_line =~ s/NOP\s+ABC/NOP DEF ABC/) {
$ctv_line = $next_line;
print "$ctv_line";
}
}
}
else {
print "$cur_line";
}
}发布于 2014-09-04 06:56:18
您自己的代码的主要问题是,大多数代码只在包含标签的行上执行,因为它在if ($cur_line =~ /^LABEL/) { ... }中,而您想要修改的行在该行之后。
如果您使用$.的值记录标签所在的行号,这是最直接的做法。然后,您可以通过减法找到相对于标签的行号,并且,由于修改具有四个一组的模式,模运算符%将告诉您是否进行替换。
请注意,它现在根据您的注释进行了修改,其中您说要跳过每十行中的两行。
像这样
use strict;
use warnings;
use 5.010;
use autodie;
open my $fh, '<', 'data.txt';
my $label_line;
while (<$fh>) {
$label_line = $. if /LABEL:/;
if ($label_line) {
s/ABC/DEF ABC/ if ( $. - $label_line ) % 10 >= 2;
}
print;
}输出
some lines
some lines
LABEL:
NOP ABC some text - line 1
NOP DEF ABC some text - line 2
NOP DEF ABC some text - line 3
NOP DEF ABC some text - line 4
NOP DEF ABC some text - line 5
NOP DEF ABC some text - line 6
NOP DEF ABC some text - line 7
NOP DEF ABC some text - line 8
NOP DEF ABC some text - line 9
NOP ABC some text - line 10
NOP ABC some text - line 11
NOP DEF ABC some text - line 12
NOP DEF ABC some text - line 13
NOP DEF ABC some text - line 14
NOP DEF ABC some text - line 15
NOP DEF ABC some text - line 16
NOP DEF ABC some text - line 17
NOP DEF ABC some text - line 18
NOP DEF ABC some text - line 19
NOP ABC some text - line 20
NOP ABC some text - line 21
NOP DEF ABC some text - line 22
NOP DEF ABC some text - line 23
NOP DEF ABC some text - line 24
NOP DEF ABC some text - line 25
NOP DEF ABC some text - line 26
NOP DEF ABC some text - line 27
NOP DEF ABC some text - line 28
NOP DEF ABC some text - line 29发布于 2014-09-04 07:42:52
使用flip-flop operator确定匹配标签后的行号:
use strict;
use warnings;
while (<DATA>) {
if (my $range = /LABEL/ .. undef) {
s/(?=ABC)/DEF / if ($range - 1) % 4 > 1;
}
print;
}
__DATA__
some lines
some lines
LABEL:
NOP ABC some text - line 1
NOP ABC some text - line 2
NOP ABC some text - line 3
NOP ABC some text - line 4
NOP ABC some text - line 5
NOP ABC some text - line 6
NOP ABC some text - line 7
NOP ABC some text - line 8
NOP ABC some text - line 9
NOP ABC some text - line 10
NOP ABC some text - line 11输出:
some lines
some lines
LABEL:
NOP ABC some text - line 1
NOP DEF ABC some text - line 2
NOP DEF ABC some text - line 3
NOP ABC some text - line 4
NOP ABC some text - line 5
NOP DEF ABC some text - line 6
NOP DEF ABC some text - line 7
NOP ABC some text - line 8
NOP ABC some text - line 9
NOP DEF ABC some text - line 10
NOP DEF ABC some text - line 11漫游规范更新
您在评论中陈述了以下内容:
感谢您的反馈。然而,在我的实际文件中(我只是想展示一个例子),我必须跳过label之后的下一行,用DEF ABC修改下8行,跳过下2行,然后再次修改下8行。你能告诉我如何做到这一点吗?对不起,我对Perl还不太熟悉。
通过将脚本更改为以下内容,可以轻松接受这一点:
while (<DATA>) {
if (my $range = /LABEL/ .. undef) {
s/(?=ABC)/DEF / if ($range - 1) % 10 > 1;
}
print;
}https://stackoverflow.com/questions/25654775
复制相似问题