gpt4 book ai didi

bash - 从 12GB 文件中删除特定行

转载 作者:行者123 更新时间:2023-11-29 08:53:03 25 4
gpt4 key购买 nike

我正在尝试从 12GB 的文本文件中删除特定行。

我在 HP-UX 上没有可用的 sed -i 选项,其他选项(如保存到临时文件)也不起作用,因为我只有 20GB 可用空间,其中 12GB 已用通过文本文件。

考虑到空间要求,我正在尝试使用 Perl 来完成此操作。

此解决方案可从 12 GB 的文件中删除最后 9 行。

#!/usr/bin/env perl

use strict;
use warnings;

use Tie::File;

tie my @lines, 'Tie::File', 'test.txt' or die "$!\n";
$#lines -= 9;
untie @lines;

我想修改上面的代码以删除任何特定的行号。

最佳答案

Tie::File 永远不是答案。

  • 出奇地慢。
  • 即使您限制其缓冲区的大小,它也可能比将整个文件拖入内存消耗更多的内存。

您同时遇到了这两个问题。您遇到文件的每一行,因此 Tie::File 将读取整个文件并将每一行的索引存储在内存中。这在 64 位构建的 Perl 上每行占用 28 个字节(不计算内存分配器中的任何开销)。


要删除文件的最后 9 行,您可以使用以下命令:

use File::ReadBackwards qw( );

my $qfn = '...';

my $pos;
{
my $bw = File::ReadBackwards->new($qfn)
or die("Can't open \"$qfn\": $!\n");

for (1..9) {
defined( my $line = $bw->readline() )
or last;
}

$pos = $bw->tell();
}

# Can't use $bw->get_handle because it's a read-only handle.
truncate($qfn, $pos)
or die("Can't truncate \"$qfn\": $!\n");

要删除任意行,您可以使用以下命令:

my $qfn = '...';

open(my $fh_src, '<:raw', $qfn)
or die("Can't open \"$qfn\": $!\n");
open(my $fh_dst, '+<:raw', $qfn)
or die("Can't open \"$qfn\": $!\n");

while (<$fh_src>) {
next if $. == 9; # Or "if /keyword/", or whatever condition you want.

print($fh_dst $_)
or die($!);
}

truncate($fh_dst, tell($fh_dst))
or die($!);

以下优化版本假定只有一行(或一行)要删除:

use Fcntl qw( SEEK_CUR SEEK_SET );

use constant BLOCK_SIZE => 4*1024*1024;

my $qfn = 'file';

open(my $fh_src, '<:raw', $qfn)
or die("Can't open \"$qfn\": $!\n");
open(my $fh_dst, '+<:raw', $qfn)
or die("Can't open \"$qfn\": $!\n");

my $dst_pos;
while (1) {
$dst_pos = tell($fh_src);
defined( my $line = <$fh_src> )
or do {
$dst_pos = undef;
last;
};

last if $. == 9; # Or "if /keyword/", or whatever condition you want.
}

if (defined($dst_pos)) {
# We're switching from buffered I/O to unbuffered I/O,
# so we need to move the system file pointer from where the
# buffered read left off to where we actually finished reading.
sysseek($fh_src, tell($fh_src), SEEK_SET)
or die($!);

sysseek($fh_dst, $dst_pos, SEEK_SET)
or die($!);

while (1) {
my $rv = sysread($fh_src, my $buf, BLOCK_SIZE);
die($!) if !defined($rv);
last if !$rv;

my $written = 0;
while ($written < length($buf)) {
my $rv = syswrite($fh_dst, $buf, length($buf)-$written, $written);
die($!) if !defined($rv);
$written += $rv;
}
}

# Must use sysseek instead of tell with sysread/syswrite.
truncate($fh_dst, sysseek($fh_dst, 0, SEEK_CUR))
or die($!);
}

关于bash - 从 12GB 文件中删除特定行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50067877/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com