如何随机抽样文件内容?

时间:2009-06-23 19:55:31

标签: perl file random sample

我有一个包含内容的文件

abc
def
high
lmn
...
...

文件中有超过200万行。 我想从文件中随机采样行并输出50K行。有关如何解决这个问题的任何想法?我正在考虑Perl及其rand函数(或者一个方便的shell命令会很整洁)。

相关(可能重复)问题:

5 个答案:

答案 0 :(得分:12)

假设你基本上想要输出大约2.5%的所有行,那么这样做:

print if 0.025 > rand while <$input>;

答案 1 :(得分:5)

壳牌方式:

sort -R file | head -n 50000

答案 2 :(得分:3)

来自perlfaq5: "How do I select a random line from a file?"


如果没有将文件加载到数据库或预先索引文件中的行,那么您可以做几件事。

以下是Camel Book中的油藏采样算法:

srand;
rand($.) < 1 && ($line = $_) while <>;

这在阅读整个文件的空间方面具有明显的优势。你可以在Donald E的计算机编程艺术,第2卷,第3.4.2节中找到这种方法的证明。 .Knuth。

您可以使用File :: Random模块为该算法提供函数:

use File::Random qw/random_line/;
my $line = random_line($filename);

另一种方法是使用Tie :: File模块,它将整个文件视为一个数组。只需访问随机数组元素。

答案 3 :(得分:2)

如果您需要提取确切的行数:

use strict;
use warnings;

# Number of lines to pick and file to pick from
# Error checking omitted!
my ($pick, $file) = @ARGV;

open(my $fh, '<', $file)
    or die "Can't read file '$file' [$!]\n";

# count lines in file
my ($lines, $buffer);
while (sysread $fh, $buffer, 4096) {
    $lines += ($buffer =~ tr/\n//);
}

# limit number of lines to pick to number of lines in file
$pick = $lines if $pick > $lines;

# build list of N lines to pick, use a hash to prevent picking the
# same line multiple times
my %picked;
for (1 .. $pick) {
    my $n = int(rand($lines)) + 1;
    redo if $picked{$n}++
}

# loop over file extracting selected lines
seek($fh, 0, 0);
while (<$fh>) {
    print if $picked{$.};
}
close $fh;

答案 4 :(得分:2)

Perl方式:

使用CPAN。模块File::RandomLine可以完全满足您的需求。