使用perl替换第一行文件的问题

时间:2013-06-18 18:34:19

标签: perl io

我有一个看起来像这样的文件:

I,like
blah...

我想用'i,am'替换第一行来获取:

i,am
blah...

这些是大文件,所以这就是我所做的(based on this):

open(FH, "+< input.txt") or die "FAIL!";
my $header = <FH>;
chop($header);
$header =~ s/I,like/i,am/g;
seek FH, 0, 0; # go back to start of file
printf FH $header;
close FH;

但是,当我运行它时,我得到了这个:

i,amke
blah...

我看起来像是'ke'仍然存在。我该如何摆脱它?

3 个答案:

答案 0 :(得分:7)

我会做的事情可能是这样的:

perl -i -pe 'if ($. == 1) { s/.*/i,am/; }' yourfile.txt

当当前文件句柄$.的行计数器等于1时,这只会影响第一行。正则表达式将替换除换行符之外的所有内容。如果您需要它来匹配您的特定行,您可以在if语句中包含它:

perl -i -pe 'if ($. == 1 and /^I,like$/) { s/.*/i,am/; }' yourfile.txt

您还可以查看Tie::File,它允许您将文件视为数组,这意味着您只需执行$line[0] = "i,am\n"即可。但是,提到此模块可能存在性能问题。

答案 1 :(得分:3)

如果替换的长度与原始长度不同,则无法使用此技术。例如,您可以创建一个新文件,然后将其重命名为原始名称。

open my $IN,  '<', 'input.txt' or die $!;
open my $OUT, '>', 'input.new' or die $!;
my $header = <$IN>;
$header =~ s/I,like/i,am/g;
print $OUT $header;
print $OUT $_ while <$IN>;               # Just copy the rest.

close $IN;
close $OUT or die $!;
rename 'input.new', 'input.txt' or die $!;

答案 2 :(得分:1)

我只使用Tie::File

#! /usr/bin/env perl
use common::sense;
use Tie::File;

sub firstline {
  tie my @f, 'Tie::File', shift or die $!;
  $f[0] = shift;
  untie @f;
}

firstline $0, '#! ' . qx(which perl);

用法:

$ ./example
$ head -2 example
#! /bin/perl
use common::sense;