从Unix中随机选择文件中的行而不将其全部读入

53

我有一个包含1000万行的文件,我想从中随机选择1/100行。这是我编写的AWK代码,但它会先将整个文件内容读入内存中。我的电脑内存无法处理这么大的文件。有其他方法可以实现吗?

awk 'BEGIN{srand()}
!/^$/{ a[c++]=$0}
END {  
  for ( i=1;i<=c ;i++ )  { 
    num=int(rand() * c)
    if ( a[num] ) {
        print a[num]
        delete a[num]
        d++
    }
    if ( d == c/100 ) break
  }
 }' file

FYI,1000个样本就可以获得+/-3%的误差范围,而1万个样本则可以获得+/-1%的误差范围。1000万的样本量太大了。 - Steven Huwig
@Steven:非常感谢您的帮助。您是如何得出上面的MOE数字的?有什么参考资料吗?我的统计背景比较薄弱,我真的想学习更多知识。顺便说一句,您的观点似乎与下面的cadrian不同(即1%不够)。 - neversaint
1
http://www.americanresearchgroup.com/moe.html - Steven Huwig
@StevenHuwig 链接似乎已经离线。缓存:https://web.archive.org/web/20131104235055/http://www.americanresearchgroup.com/moe.html 维基百科:https://en.wikipedia.org/wiki/Margin_of_error - exic
11个回答

0
这是我的版本。下面的“c”是要从输入中选择的行数。将c作为参数留给读者作为练习,同样留给读者的是,为什么以c / NR开头的行可以可靠地选择恰好c行(假设输入至少有c行)。
#!/bin/sh

gawk '
BEGIN   { srand(); c = 5 }
c/NR >= rand() { lines[x++ % c] = $0 }
END { for (i in lines)  print lines[i] }

' "$@"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接