如何仅更改文件的第一行?

时间:2009-02-14 03:26:47

标签: perl scripting file sed

我想知道我可以在sed中使用哪种模式来更改大文件的第一行(~2 GB)。对sed的偏好只是因为我认为它必须比Python或Perl脚本更快。

文件具有以下结构:

field 1, field 2, ... field n
data

并且,考虑到每个字段的标识符中都有空格的可能性,我需要用这种方式用下划线替换每个空格:

**BEFORE** 
the first name,the second name,the first surname,a nickname, ...
data

**AFTER**
the_first_name,the_second_name,the_first_surname,a_nickname, ...
data

任何指向正确模式的指针,或其他脚本解决方案都会很棒。

5 个答案:

答案 0 :(得分:22)

编辑前10行

sed -i -e '1,10s/ /_/g'

在Perl中,您可以在标量上下文中使用触发器运算符:

perl -i -pe 's/ /_/g if 1 .. 10'

答案 1 :(得分:10)

我认为您不想使用任何需要将数据写入新文件的解决方案。

如果您非常确定所需要的是在大文本文件的第一行中将空格更改为下划线,则只需读取第一行,交换字符并将其写回原位: / p>

#!/usr/bin/env perl
use strict;

my $filename = shift;
open (FH, "+< $filename") || die "can't open $filename: $!";
my $line = <FH>;
$line =~ s/ /_/g;
seek FH, 0, 0; # go back to the start of the file
printf FH $line;
close FH;

要使用它,只需传递文件的完整路径即可更新:

# fixheader "/path/to/myfile.txt"

答案 2 :(得分:5)

你不太可能注意到Perl,Python之间有任何速度差异, 和sed。您的脚本将花费大部分时间等待IO。

如果行长度相同,则可以就地编辑,否则就可以编辑 必须创建一个新文件。

Perl:

#!/usr/bin/env perl
use strict;

my $filename = shift;
open my $in_fh, '<', $filename
  or die "Cannot open $filename for reading: $!";
my $first_line = <$in_fh>;

open my $out_fh, '>', "$filename.tmp"
  or die "Cannot open $filename.tmp for writing: $!";

$first_line =~ s/some translation/goes here/;

print {$out_fh} $first_line;
print {$out_fh} $_ while <$in_fh>; # sysread/syswrite is probably better

close $in_fh;
close $out_fh;

# overwrite original with modified copy
rename "$filename.tmp", $filename
  or warn "Failed to move $filename.tmp to $filename: $!";

答案 3 :(得分:4)

您提到的更改(用下划线替换每个空格)不会改变行的长度,因此理论上它可以在原地完成。

警告!:未经测试!

head -n 1 yourfile | sed -e 's/ /_/g' > tmpfile
dd conv=nocreat,notrunc if=tmpfile of=yourfile

我对conv=...参数不太确定,但似乎应该使dd用变换后的行覆盖原始文件的开头。

请注意,如果您想进行任何其他可能会改变线路长度的转换,请不要这样做。你必须做一个完整的副本。像这样的东西:

head -n 1 yourfile | sed -e 's/ /_/g' > tmpfile
tail -n + 2 | cat tmpfile - > transformedfile

答案 4 :(得分:-1)

这可能是一个解决方案:


use Tie::File;
tie my @array,"Tie::File","path_to_file";
$array[0] = "new text";
untie @array;

Tie::File是我最常用的模块之一,使用起来非常简单。数组中的每个元素都是文件中的一行。然而,其中一个缺点是,这会将整个文件加载到内存中。