您正在循环中执行此操作:
next if ($line =~ /ABC/);
因此,您正在读取文件,如果一行在该行的任何位置包含ABC,则跳过该行。但是,对于每隔一行,您都进行替换。最后,您将替换所有其他行上的字符串并将其打印出来,而不是打印出标签。
这就是你所说的:
-
我必须 阅读文件,直到我 找到 标签:
- 一旦找到标签
-
我必须 阅读下一行并 替换紧跟标签的一行中的单词。
所以:
遵循这些指示:
use strict;
use warnings; # Hope you're using strict and warnings
use autodie; # Program automatically dies on failed opens. No need to check
use feature qw(say); # Allows you to use say instead of print
open my $fh, "<", "file1.txt"; # Removed parentheses. It's the latest style
while (my $line = <$fh>) {
chomp $line; # Always do a chomp after a read.
if ( $line eq "ABC:" ) { # Use 'eq' to ensure an exact match for your label
say "$line"; # Print out the current line
$line = <$fh> # Read the next line
$line =~ s/old/new/; # Replace that word
}
say "$line"; # Print the line
}
close $fh; # Might as well do it right
请注意,当我使用say 时,我不必将\n 放在行尾。此外,通过阅读后执行chomp,我可以轻松匹配标签,而无需担心最后的\n。
这完全按照你说的应该做,但是有几个问题。第一个是当我们做$line = <$fh> 时,不能保证我们真的在读一行。如果文件在那里结束怎么办?
此外,在多个位置读取文件也是一种不好的做法。它使维护程序变得更加困难。为了解决这个问题,我们将使用 flag 变量。这可以让我们知道之前的行是否是标签:
use strict;
use warnings; # Hope you're using strict and warnings
use autodie; # Program automatically dies on failed opens. No need to check
use feature qw(say); # Allows you to use say instead of print
open my $fh, "<", "file1.txt"; # Removed parentheses. It's the latest style
my $tag_found = 0; # Flag isn't set
while (my $line = <$fh>) {
chomp $line; # Always do a chomp after a read.
if ( $line eq "ABC:" ) { # Use 'eq' to ensure an exact match for your label
$tag_found = 1 # We found the tag!
}
if ( $tag_found ) {
$line =~ s/old/new/; # Replace that word
$tag_found = 0; # Reset our flag variable
}
say "$line"; # Print the line
}
close $fh; # Might as well do it right
当然,我更愿意消除神秘的价值观。例如,标签应该是一个变量或常量。与您要搜索的字符串和要替换的字符串相同。
你提到这是一个词,所以你的正则表达式替换应该是这样的:
$line =~ s/\b$old_word\b/$new_word/;
\b 标记单词边界。这样,如果您想用 dog 替换单词 cat,您就不会被以下语句绊倒:
The Jeopardy category is "Say what".
您不想将category 更改为dogegory。