10

我想知道我可以在 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

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

4

5 回答 5

23

编辑前 10 行

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

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

perl -i -pe 's/ /_/g if 1 .. 10'
于 2009-02-14T15:41:43.083 回答
10

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

如果您非常确定只需将大文本文件的第一行中的空格更改为下划线,您只需阅读第一行,交换字符并将其写回原处:

#!/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"
于 2009-02-14T17:06:51.223 回答
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: $!";
于 2009-02-14T03:34:53.080 回答
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
于 2009-02-14T04:31:51.057 回答
-1

这可能是一个解决方案:


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

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

于 2009-02-14T17:07:52.640 回答