Perl 替换文本文件中的多行

Perl 替换文本文件中的多行,perl,text,replace,Perl,Text,Replace,我有包含以下文本的文本文件(除其他文本外) DIFF_COEFF=1.000e+07,1.000e+07,1.000e+07,1.000e+07, 1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07, 1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000

我有包含以下文本的文本文件(除其他文本外)

DIFF_COEFF=1.000e+07,1.000e+07,1.000e+07,1.000e+07,
1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,
1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,
1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,
1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,
1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,1.000e+07,4.000e+05,
我需要将其替换为以下文本:

DIFF_COEFF=2.000e+07,2.000e+07,2.000e+07,2.000e+07,
2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,
2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,
2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,
2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,
2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,8.000e+05,
上面的每一行对应于文本文件中的新行

在谷歌搜索了一番之后,我认为在下面的文章中使用Perl可能会奏效,但事实并非如此。我收到了错误信息

在-e第1行,块1处被零非法除法

s_orig='DIFF_COEFF=*4.000e+05,'
2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+07、2.000e+7、2.000e+7、2.000e+7、2.000e+7、2.000e+7、2.000e+07、2.000e+07、2.000e+07、2.000e+07、7、2.000e+7、7 E+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,\n2.000e+07,2.000e+07,2.000e+07,2.000e+07,2.000e+07,8.000e+05,'
perl-0-i-pe“s:\Q${s_orig}\E:${s_new}:/igs”file.txt
这里有人知道正确的方法吗


编辑-更多详细信息:此块后面的文本是“DIFF_COEFF_Q=”后跟同一组数字,因此我需要搜索并替换显示的特定行。文本文件的大小不是很大。

将文件复制到一个新的文件上,但在这些标记之间的文本范围内,删除替换文本。然后移动该文件以替换原始文件,因为根据问题中尝试的
perl-0-i
判断可能需要该文件

请注意,更改文件时,我们必须构建新内容,然后替换该文件。有几种方法可以做到这一点,下面将进一步展示一些使之更容易的模块

下面的代码使用,并且它返回范围内行的计数器,第一个为
1
,最后一个为
E0
。因此,在最后一行写入替换文本(和post区域结束标记)时,我们不会复制该区域内的行

我认为感兴趣的区域在“代码> > DeffCoffEffq=< /代码>行之前结束,按问题编辑.< /P>

use warnings;
use strict;
use feature 'say';
use File::Copy 'move';

my $replacement = "replacement text";

my $file     = 'input.txt';
my $out_file = 'new_' . $file;

open my $fh_out, '>', $out_file or die "Can't open $out_file: $!";
open my $fh,     '<', $file     or die "Can't open $file: $!";

while (<$fh>) 
{
    if (my $range_cnt = /^\s*DIFF_COEFF\s*=/ .. /^\s*DIFF_COEFF_Q\s*=/) #/
    {
        if ($range_cnt =~ /E0$/)
        {
            print $fh_out $replacement;  # may need a newline
            print $fh_out $_;         
        }
    }   
    else { 
        print $fh_out $_; 
    }
}
close $fh     or die "Can't close $file: $!";      # don't overwrite original
close $fh_out or die "Can't close $out_file: $!";  # if there are problems

#move $out_file, $file or die "Can't move $file to $out_file: $!";
这里的
/m
修饰符用于多行模式,在这种模式下,我们可以使用
^
作为行的开头(而不是整个字符串),这在这里很有用。
/s
使
也匹配一个换行符。还请注意,我们可以使用
Path::Tiny
简单地对文件进行slurp,如下所示:
my$text=Path($file)->slurp

另一个选择是使用,在较新的版本中,它具有和方法

有关这方面的更多信息,请参见,例如,和


第一种和最后一种方法是更改文件的inode编号。查看是否有问题。

将文件复制到新文件,但在这些标记之间的文本范围内,将替换文本替换掉。然后移动该文件以替换原始文件,因为根据问题中尝试的
perl-0-i
判断可能需要该文件

请注意,更改文件时,我们必须构建新内容,然后替换该文件。有几种方法可以做到这一点,下面将进一步展示一些使之更容易的模块

下面的代码使用,并且它返回范围内行的计数器,第一个为
1
,最后一个为
E0
。因此,在最后一行写入替换文本(和post区域结束标记)时,我们不会复制该区域内的行

我认为感兴趣的区域在“代码> > DeffCoffEffq=< /代码>行之前结束,按问题编辑.< /P>

use warnings;
use strict;
use feature 'say';
use File::Copy 'move';

my $replacement = "replacement text";

my $file     = 'input.txt';
my $out_file = 'new_' . $file;

open my $fh_out, '>', $out_file or die "Can't open $out_file: $!";
open my $fh,     '<', $file     or die "Can't open $file: $!";

while (<$fh>) 
{
    if (my $range_cnt = /^\s*DIFF_COEFF\s*=/ .. /^\s*DIFF_COEFF_Q\s*=/) #/
    {
        if ($range_cnt =~ /E0$/)
        {
            print $fh_out $replacement;  # may need a newline
            print $fh_out $_;         
        }
    }   
    else { 
        print $fh_out $_; 
    }
}
close $fh     or die "Can't close $file: $!";      # don't overwrite original
close $fh_out or die "Can't close $out_file: $!";  # if there are problems

#move $out_file, $file or die "Can't move $file to $out_file: $!";
这里的
/m
修饰符用于多行模式,在这种模式下,我们可以使用
^
作为行的开头(而不是整个字符串),这在这里很有用。
/s
使
也匹配一个换行符。还请注意,我们可以使用
Path::Tiny
简单地对文件进行slurp,如下所示:
my$text=Path($file)->slurp

另一个选择是使用,在较新的版本中,它具有和方法

有关这方面的更多信息,请参见,例如,和


第一种和最后一种方法是更改文件的inode编号。看看这是否是个问题。

这是你犯的一个有趣的错误,我可以看出是什么导致你犯的错误。但我想我从未见过其他人犯过同样的错误:-)

您的替代声明如下:

s:\Q${s_orig}\E:${s_new}:/igs
因此,您决定使用
作为替换运算符的分隔符。但是你想使用选项
i
g
s
,在你所看到的任何地方,人们谈论替换操作符的选项,他们谈论使用
/
来引入选项。因此,您已将
/igs
添加到替换运算符中

但是您遗漏了(我完全理解为什么)选项之前的
/
实际上是标准的结束分隔符,
s/../../
,替换运算符的版本。如果您更改了分隔符(正如您所做的那样),那么您只需要更改结束分隔符即可

在您的例子中,Perl不期望使用
/
,因为它已经看到了结束分隔符。因此,它决定
s:\Q${s_orig}\E:${s_new}:/igs
s:\Q${s_orig}\E:${s_new}:/igs
s:\Q${s_orig}\E:${s_new}:igs