我有一个包含5000万行的文件,我必须随机输出1000行。
首先,我创建了1000个随机数;然后我用
sed -n "$random{p;q}" file
它真的很慢;一行输出至少需要5-6秒。
所以我认为我应该优化打印特定的线速度。
我们有很多方法可以打印特定的行:
sed -n "$line{p;q}" file
awk "NR==$line{print}" file
head -$line file | tail -1
一切都很慢......打印特定行需要大约5-6秒。
shell中是否还有其他方法可以打印特定的行?或者python,perl可以比shell快吗?或者我解决这个问题的方法错了?
---------------------------------------- SPLIT ------ ----------------------------------------
迭代1000个随机数,每次使用shell一次,可以生成1000次io操作。也许我应该先使用数组保存随机数并迭代文件一次。
random_array=()
awk '{if ( NR in $random_array ) print;}' file
好吧,我会以这种方式测试并稍后粘贴结果
答案 0 :(得分:2)
为避免读取整个文件,您可以获取文件的大小,然后生成0到该数字之间的1000个偏移的列表。这些通常是位于一行中间的位置,但您可以阅读下一个换行符,然后阅读并打印以下行。但是,这会对文件的第一行引入偏差。如果您对平均线长度进行了估计,则可以从生成的偏移量中减去该数字(任何负面结果都意味着从偏移量0读取和打印。)
这是一个概念的快速证明。为了便于说明,我假设平均线长约为75个字符。这也会影响公平性(选择长线后的线的可能性更高)。最后一行的处理也不公平;如果它短于75个字符,则永远不会被选中(!) - 您可以尝试通过计算实际读取的行的实际平均线长来解决这个问题,但我将其留作练习,以便保持这个例子相当紧凑。
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl (qw(SEEK_SET SEEK_CUR SEEK_END));
my $n = (defined @ARGV ? shift @ARGV : '--help');
die "Syntax: $0 number file\n" unless @ARGV == 1 and $n =~ m/^[0-9]+$/;
open (F, "<", $ARGV[0]) or die "$0: Could not open $ARGV[0]: $!\n";
seek (F, 0, SEEK_END) or die "$0: Could not SEEK_END $ARGV[0]: $!\n";
my $max = tell(F);
my %seen;
for (my $i=0; $i < $n; ++$i)
{
my $offset = int(rand($max))-75;
my $first = 0;
if ($offset < 0)
{
$offset = 0;
$first = 1;
}
seek (F, $offset, SEEK_SET)
or die "$0: Could not SEEK_SET $ARGV[0]: $!\n";
<F> unless $first;
redo if eof (F); # Cheap trick, just retry if at eof
redo if $seen{tell(F)}++;
print scalar(<F>);
}
我添加了代码以避免重复;这是%seen
哈希。
答案 1 :(得分:1)
按文件中的行顺序,内存中没有所有行:
awk '
NR==FNR { next }
FNR==1{
srand;
n=NR-1
for(i=1; i<=1000; i++) {
line=0
while(!line || line in A) line=int(rand*n)+1
A[line]
}
}
FNR in A
' infile infile
答案 2 :(得分:0)
无论您使用哪种工具,找到这些线都有固有的成本。实质上,您需要每次遍历该大文件,查找并计算换行符号。
我可以看到两种解决方案:
一次性预先计算文件中的行偏移量,然后使用lseek
查找打印件。您可以存储每个第100或第1000行偏移以节省空间。
预先生成整个行号列表,并在文件中一次性收集行。然后打印出来。 (如果您希望线条的顺序是随机的,则无法打印出来。)
其中任何一个在shell中都很难做到。对于仅限shell的解决方案,请尝试devnull的建议shuf
。但不是1,你想要使用1000:
shuf -n 1000 file
答案 3 :(得分:0)
如果您只想要更大规模数据文件中的特定行,则会根据您的请求增加成本。如果您的文件在一段时间(一周或更长时间)内不可变,则需要进行预处理,只有一个解决方案可以解决您的问题:
如您所知,以上只是一种方法。