繁体   English   中英

使用perl修改文件中的字符串

[英]Modify a string in a file with perl

我有一个文件d00.dat,我需要将字符串d01更改为d02 ...使用以下代码,它将在控制台中打印修改内容,但它们在文件d00.dat中没有更改...我该如何更改去做?

my $line = 0;
my $filename = "d00.dat";
open(my $fh, '<', $filename) || die "file could not open $! \n";
while( $line = <$fh>) {
if( $line =~ s/d01/d02/g ){
print "$line\n";
}

最简单,最快的解决方案是将文件读入内存,进行更改,然后将更改写回到文件中。

my $qfn = "d00.dat";

my $file;
{
   open(my $fh, '<', $qfn)
      or die("Can't open \"$qfn\": $!\n");

   local $/;
   $file = <$fh>;
}

$file =~ s/d01/d02/g;

{
   open(my $fh, '>', $qfn)
      or die("Can't create \"$qfn\": $!\n");

   print($fh $file);
}

作为单线:

perl -i -pe's/d01/d02/g' d00.dat

如果您只想更改这些位置,则不必-不得不替换整个文件。

您可以将包括更改在内的每一行打印到另一个文件,然后将其复制。 许多工具都以这种方式工作。 或者,您可以读取所有行,对其进行适当更改,然后覆盖文件。

my $filename = "d00.dat";

open(my $fh, '<', $filename) || die "file could not open $! \n";
my @new_lines = map { s/d01/d02/g; $_ } <$fh>;
close $fh;

open(my $fh_out, '>', $filename) || die "file could not open $! \n";
print $fh_out $_  for @new_lines;
close $fh_out;

由于open将关闭文件句柄(如果已打开),您也可以执行

open my $fh, '<', $filename or die "Can't open $filename: $!";
my @new_lines = map { s/d01/d02/gr } <$fh>;

open $fh, '>', $filename or die "Can't open $filename: $!";
print $fh $_  for @new_lines;
close $fh;

我在其中删除parens并将其更改为or ,然后将$filename添加到错误消息中。 我还在正则表达式中使用了/r修饰符(“ 非破坏性替换 ”),通过它返回更改后的字符串-正是该map所需的字符串,因此现在我们不需要在末尾使用单独的$_块。

问题中出现的die消息末尾的换行符有一个微妙的结果:它抑制了有关发出die的行号的信息。 虽然这有时期望,在大多数情况下,它是不是在这里我们当然希望看到调用,它失败的行号! 因此,我在die的消息中删除了该额外的换行符。


文件是字节序列。 因此,如果我们想用yes代替一个nope ...当我们替换了前三个字符时,最后一个字符e会发生什么? 我们必须按照原始的nope移动文件的其余部分,以覆盖e ,因此现在遵循yes 因此,我们需要覆盖文件的其余部分,实际上,仅替换整个文件要容易得多。

如果我们想用yeah代替nope ...好吧,现在是4比4,实际上我们可以覆盖这4个字符。 但是,这种情况很少发生,并且执行起来更加复杂。

当问题要求用d02替换d01 ,我想这是一个示例,而实际上字符串的长度通常不相同。 即使他们正在...替换文件也更加容易和安全,并且很可能不会发现效率损失。

Perl有一个开关可以就地修改文件。 我认为这就是您要寻找的:

perl -i.bak -p -e 's/d01/d02/g;' d00.dat

这将

  • d00.dat重命名为d00.dat.bak
  • 读取d00.dat.bak
  • d02替换每次出现的d01
  • 将结果行打印到d00.dat

说明:

  • -i就地编辑文件,如果给定了一些后缀,则可以选择进行备份。 例如, -i.bak将创建$file.bak-i.before将创建$file.before等。如果没有后缀(仅-i ),将没有备份,因此请考虑这样做是危险的。

  • -p放置像

     while(<>) { # your code print; } 

    在这种情况下( s/…/…/g;

  • -e仅仅表示“执行以下语句”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM