2

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

I,like
blah...

我只想用 'i,am' 替换第一行以获得:

i,am
blah...

这些是大文件,所以这就是我所做的(基于此):

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...

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

4

3 回答 3

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". 但是,有人提到此模块可能存在性能问题。

于 2013-06-18T18:47:11.280 回答
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 $!;
于 2013-06-18T18:40:15.830 回答
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;
于 2013-06-19T01:25:00.727 回答