我有一小段代码,通过在模式匹配的基础上在行前面插入#
来为文件添加注释。我面临的挑战是将#
添加到下一行。这是我到目前为止编写的代码:
#!/usr/bin/perl
use warnings;
open(FILE, "<extensions.txt") || die "File not found";
my @lines = <FILE>;
close(FILE);
my @newlines;
foreach(@lines) {
$_ =~ s/\[google\.com/\#\[google\.com/g;
push(@newlines,$_);
}
open(FILE, ">ext.txt") || die "File not found";
print FILE @newlines;
close(FILE);
因此,这会搜索以[google
开头的任何行,并将其替换为#[google
。我也要评论下一行。
这是一个示例文件:
[google.com]
Once upon a time...
[google.com-out-outnew]
Meanwhile, in the land of ...
[yahoo.com]
Centuries ago, the scion of ....
一旦我运行上面的脚本,我得到:
#[google.com]
Once upon a time...
#[google.com-out-outnew]
Meanwhile, in the land of ...
[yahoo.com]
Centuries ago, the scion of ....
以下是我正在寻找的输出示例:
#[google.com]
#Once upon a time...
#[google.com-out-outnew]
#Meanwhile, in the land of ...
[yahoo.com]
Centuries ago, the scion of ....
我知道它应该在这一行$_ =~ s/\[google\.com/\#\[google\.com/g;
之后,但我感到困惑的是如何修改下一行,然后在循环中跳过它。有人可以解释一下这是怎么回事吗?
答案 0 :(得分:3)
这是一个单行,可以(至少)两种方式完成:
> perl -pwe'$_ .= "#" . <> if s/(?=\Q[google.com\E)/#/g;' google.txt
#[google.com]
#Once upon a time...
#[google.com-out-outnew]
#Meanwhile, in the land of ...
[yahoo.com]
Centuries ago, the scion of ....
如果执行替换,则下一行<>
将附加到当前行$_
。替换只是lookahead assertion与quotemeta escape \Q ... \E
相结合,会在匹配的文本前插入#
。
一个小小的警告是,如果在文件的最后一行找到字符串,您将收到未初始化的警告,因为文件句柄将在eof处返回undef
。另一个未处理的边缘情况是,如果你连续两行google
,但我认为你的格式不允许。
处理此问题的另一种方法是使用段落模式,因为您的记录似乎是由双换行符(空行)分隔。
perl -00 -lpwe's/^/#/gm if /^\Q[google.com\E/' google.txt
请注意,这需要使用/m
和/g
修饰符,这允许^
分别匹配换行符和多个匹配项。 -00
将输入记录分隔符更改为""
(\n\n
的特殊情况),它会将整个记录读入$_
。 -l
开关将在替换前删除新的输入记录分隔符\n\n
以避免额外的#
,并在完成后替换它。
您可以将单行运行作为就地编辑,或将输出重定向到新文件
perl -pi.bak -we ' ...' yourfile.txt # in-place edit with backup
perl -pwe ' ... ' yourfile.txt > new.txt # redirect to new file
答案 1 :(得分:2)
只需设置一个等于是否找到模式的标志,然后打印前面带有'#'的行,如果是,则重置标志,然后跳到下一个循环迭代。
您可以查看s///
operator的结果,即替换次数。
这是根据现代Perl实践重写的代码,并进行了优化,因此您不需要数组。
#!/usr/bin/perl
use strict;
my $pattern_found;
open my $file_in, "<extensions.txt" or die $!;
open my $file_out, ">ext.txt" or die $!;
while (<$file_in>) {
if ($pattern_found) {
$pattern_found = 0;
print $file_out "#$_";
next
}
$pattern_found = $_ =~ s/\[google\.com/\#\[google\.com/g;
print $file_out $_;
}
答案 2 :(得分:0)
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $srcfile = 'extensions.txt';
my $outfile = 'ext.txt';
open my $infh, '<', $srcfile;
open my $outfh, '>', $outfile;
my $comment_next_line = 0;
while (<$infh>) {
if ($comment_next_line) {
$comment_next_line = 0;
s/^/#/;
} elsif (s/(?=\[google\.com)/#/g) {
$comment_next_line = 1;
}
$outfh->print($_);
}