搜索并替换文件中的多行
Search and replace multiple lines from a file
我正在尝试删除 a.txt
文件的一部分并替换为 b.txt
文件的内容,同时还使用 Perl 程序修改 a.txt
中的其他行。
文件a.txt
line1
line2
replace from below line
replace from this line
bla bla...
bla bla...
to this line
line3
line4
文件b.txt
replacement1
replacement2
replacementn
下面是我的代码,但无法正常工作。
#!/apps/perl/5.8.3/bin/perl -w
open (INPUT, "a.txt") or die $!;
open (REPLACE, "b.txt") or die $!;
open (OUTPUT, ">c.txt") or die $!;
my $replace_text;
{
local $/;
$replace_text = <REPLACE>;
}
close(REPLACE);
while (<INPUT>) {
s/line1/modified_line1/;
s/line2/modified_line2/;
if($_ =~ /replace from below line/){
while(<INPUT>){
{
local undef $/;
s/replace from this line.*to this line/$replace_text/smg;
}
s/line3/modified_line3/;
s/line4/modified_line4/;
print OUTPUT;
}
}
}
close(INPUT);
close(OUTPUT);
预期输出文件c.txt
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
有人可以帮助我了解哪里出错了吗?
我认为您不需要嵌套 while
循环来读取您的输入文件。
一种方法是使用变量来控制打印到输出文件的时间:
use warnings;
use strict;
open (INPUT, "a.txt") or die $!;
open (REPLACE, "b.txt") or die $!;
open (OUTPUT, ">c.txt") or die $!;
my $replace_text;
{
local $/;
$replace_text = <REPLACE>;
}
close(REPLACE);
my $print = 1;
while (<INPUT>) {
s/line(\d)/modified_line/;
$print = 0 if /replace from below line/;
if (/to this line/) {
$print = 1;
$_ = $replace_text;
}
print OUTPUT if $print;
}
close(INPUT);
close(OUTPUT);
输出:
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
我还使用 \d
将你的 4 个 line
替换合并为 1 个。
尽管我很喜欢perl,但这里真的没有必要:
sed -e 's/line1/modified_line1/' \
-e 's/line2/modified_line2/' \
-e 's/line3/modified_line3/' \
-e 's/line4/modified_line4/' \
-e '/replace from below/rb.txt' \
-e '/replace from below/,/to this line/d' a.txt
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
如果你确实想使用 perl,我会这样做:
#!/usr/bin/env perl
use strict;
use warnings;
open my $ah, '<', "a.txt" or die "a.txt: $!\n";
while(<$ah>) {
s/line1/modified_line1/;
s/line2/modified_line2/;
s/line3/modified_line3/;
s/line4/modified_line4/;
if( /replace from below/ ){
system "cat b.txt" and exit 1;
}
next if( /replace from below/ .. /to this line/);
print;
}
问题描述没有指定a.txt
文件可以有多大。发布的代码使用带有修饰符 /smg
的正则表达式,这表明 OP 尝试处理多行文本。
假设输入文件足够小,可以在内存中读取和处理。
为了代码可管理性,替代品放入 __DATA__
块中,该块读取 %substitute
哈希。
基于 keys %substitute
构建正则表达式 $re
以在替换模式中使用。
多行替换基于原始OP的代码(不适用于逐行读取输入数据)。
定义了两个子例程以将文件内容读入变量并将变量数据存储到文件中 -- 只是为了使代码更易于阅读和理解。
use strict;
use warnings;
use feature 'say';
my($fname_in,$fname_repl,$fname_out) = qw/a.txt b.txt c.txt/;
my %substitute = split(/[,\s]/, do{ local $/; <DATA>} );
my $re = '\b(' . join('|',keys %substitute) . ')\b';
my $data = read_file($fname_in);
my $replace_with = read_file($fname_repl);
$data =~ s/$re/$substitute{}/g;
$data =~ s/replace from below line.*?to this line/$replace_with/gsm;
save_file($fname_out,$data);
say $data;
exit 0;
sub read_file {
my $fname = shift;
my $data;
open my $fh, '<', $fname
or die "Couldn't open $fname";
$data = do { local $/; <$fh> };
close $fh;
return $data;
}
sub save_file {
my $fname = shift;
my $data = shift;
open my $fh, '>', $fname
or die "Couldn't open $fname";
say $fh $data;
close $fh;
}
__DATA__
line1,modified_line1
line2,modified_line2
line3,modified_line3
line4,modified_line4
输出
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
我正在尝试删除 a.txt
文件的一部分并替换为 b.txt
文件的内容,同时还使用 Perl 程序修改 a.txt
中的其他行。
文件a.txt
line1
line2
replace from below line
replace from this line
bla bla...
bla bla...
to this line
line3
line4
文件b.txt
replacement1
replacement2
replacementn
下面是我的代码,但无法正常工作。
#!/apps/perl/5.8.3/bin/perl -w
open (INPUT, "a.txt") or die $!;
open (REPLACE, "b.txt") or die $!;
open (OUTPUT, ">c.txt") or die $!;
my $replace_text;
{
local $/;
$replace_text = <REPLACE>;
}
close(REPLACE);
while (<INPUT>) {
s/line1/modified_line1/;
s/line2/modified_line2/;
if($_ =~ /replace from below line/){
while(<INPUT>){
{
local undef $/;
s/replace from this line.*to this line/$replace_text/smg;
}
s/line3/modified_line3/;
s/line4/modified_line4/;
print OUTPUT;
}
}
}
close(INPUT);
close(OUTPUT);
预期输出文件c.txt
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
有人可以帮助我了解哪里出错了吗?
我认为您不需要嵌套 while
循环来读取您的输入文件。
一种方法是使用变量来控制打印到输出文件的时间:
use warnings;
use strict;
open (INPUT, "a.txt") or die $!;
open (REPLACE, "b.txt") or die $!;
open (OUTPUT, ">c.txt") or die $!;
my $replace_text;
{
local $/;
$replace_text = <REPLACE>;
}
close(REPLACE);
my $print = 1;
while (<INPUT>) {
s/line(\d)/modified_line/;
$print = 0 if /replace from below line/;
if (/to this line/) {
$print = 1;
$_ = $replace_text;
}
print OUTPUT if $print;
}
close(INPUT);
close(OUTPUT);
输出:
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
我还使用 \d
将你的 4 个 line
替换合并为 1 个。
尽管我很喜欢perl,但这里真的没有必要:
sed -e 's/line1/modified_line1/' \
-e 's/line2/modified_line2/' \
-e 's/line3/modified_line3/' \
-e 's/line4/modified_line4/' \
-e '/replace from below/rb.txt' \
-e '/replace from below/,/to this line/d' a.txt
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4
如果你确实想使用 perl,我会这样做:
#!/usr/bin/env perl
use strict;
use warnings;
open my $ah, '<', "a.txt" or die "a.txt: $!\n";
while(<$ah>) {
s/line1/modified_line1/;
s/line2/modified_line2/;
s/line3/modified_line3/;
s/line4/modified_line4/;
if( /replace from below/ ){
system "cat b.txt" and exit 1;
}
next if( /replace from below/ .. /to this line/);
print;
}
问题描述没有指定a.txt
文件可以有多大。发布的代码使用带有修饰符 /smg
的正则表达式,这表明 OP 尝试处理多行文本。
假设输入文件足够小,可以在内存中读取和处理。
为了代码可管理性,替代品放入 __DATA__
块中,该块读取 %substitute
哈希。
基于 keys %substitute
构建正则表达式 $re
以在替换模式中使用。
多行替换基于原始OP的代码(不适用于逐行读取输入数据)。
定义了两个子例程以将文件内容读入变量并将变量数据存储到文件中 -- 只是为了使代码更易于阅读和理解。
use strict;
use warnings;
use feature 'say';
my($fname_in,$fname_repl,$fname_out) = qw/a.txt b.txt c.txt/;
my %substitute = split(/[,\s]/, do{ local $/; <DATA>} );
my $re = '\b(' . join('|',keys %substitute) . ')\b';
my $data = read_file($fname_in);
my $replace_with = read_file($fname_repl);
$data =~ s/$re/$substitute{}/g;
$data =~ s/replace from below line.*?to this line/$replace_with/gsm;
save_file($fname_out,$data);
say $data;
exit 0;
sub read_file {
my $fname = shift;
my $data;
open my $fh, '<', $fname
or die "Couldn't open $fname";
$data = do { local $/; <$fh> };
close $fh;
return $data;
}
sub save_file {
my $fname = shift;
my $data = shift;
open my $fh, '>', $fname
or die "Couldn't open $fname";
say $fh $data;
close $fh;
}
__DATA__
line1,modified_line1
line2,modified_line2
line3,modified_line3
line4,modified_line4
输出
modified_line1
modified_line2
replacement1
replacement2
replacementn
modified_line3
modified_line4