从文件中选择随机行


240

在Bash脚本中,我想从输入文件中挑选出N条随机行并输出到另一个文件。

如何才能做到这一点?


随机排序文件并选择N首行。
Piotr Praszmo'2


31
这不是重复的-他想要N行vs 1行。
OneSolitaryNoob,2015年


1
我不同意sort -R这一点,因为它做了很多额外的工作,尤其是对于长文件。您可以使用$RANDOM% wc -ljotsed -n(点菜stackoverflow.com/a/6022431/563329)和bash功能(阵列,命令重定向等)来定义自己的peek功能,这将在500万行的文件实际运行。
同构

Answers:


627

shuf-n如下所示的选项一起使用,以获得N随机行:

shuf -n N input > output

2
如果您只需要一组随机的行而不是随机的顺序,那么shuf效率很低(对于大文件):更好的方法是进行储层采样,如本答案所示
petrelharp 2015年

我在500M行文件上运行此程序以提取1,000行,这花了13分钟。该文件已有几个月没有被访问,并且位于Amazon EC2 SSD驱动器上。
T. Brian Jones

那么从本质上讲这sort -R是否更随机?
蒙娜·贾拉勒

1
@MonaJalal不会更快,因为它根本不需要比较行。
rogerdpack

最终是否会多次产生同一行?
Frederick Nord

161

随机排序文件并选择第一100行:

$ sort -R input | head -n 100 >output

43
sort实际上将相同的行排序在一起,因此,如果您可能有重复的行,并且已shuf安装(一个gnu工具),则最好将其用于此目的。
凯文(Kevin)

22
而且,如果您有一个很大的文件(80kk行),这肯定会让您等待很多,而shuf -n操作却是瞬时的。
鲁本斯

28
sort -R在Mac OS X(10.9)下不可用
Mirko Ebert

2
@ tfb785:sort -R可能是GNU选项,请安装GNU coreutils。顺便说一句,shuf也是coreutils的一部分。
jfs 2014年

1
@JFSebastian代码:sort -R input | head -n <num_lines>。输入文件为279GB,带有2bi +行。但是无法分享。无论如何,关键是您可以通过随机播放将某些行保留在内存中,以随机选择要输出的内容。无论您需要什么,排序都会对整个文件进行排序。
鲁本斯

18

好吧,根据对这个简短回答的评论,他在一分钟之内就删掉了78000亿行。

接受挑战...

首先,我需要一个78.000.000.000行的文件:

seq 1 78 | xargs -n 1 -P 16 -I% seq 1 1000 | xargs -n 1 -P 16 -I% echo "" > lines_78000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000.txt > lines_78000000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000000.txt > lines_78000000000.txt

这给了我一个780亿的文件换行符的 ;-)

现在,对于shuf部分:

$ time shuf -n 10 lines_78000000000.txt










shuf -n 10 lines_78000000000.txt  2171.20s user 22.17s system 99% cpu 36:35.80 total

瓶颈是CPU,并且不使用多个线程,它以100%固定1个内核,其余15个未使用。

我经常使用Python,因此将使它变得更快:

#!/bin/python3
import random
f = open("lines_78000000000.txt", "rt")
count = 0
while 1:
  buffer = f.read(65536)
  if not buffer: break
  count += buffer.count('\n')

for i in range(10):
  f.readline(random.randint(1, count))

这让我不到一分钟:

$ time ./shuf.py         










./shuf.py  42.57s user 16.19s system 98% cpu 59.752 total

我使用i9和Samsung NVMe在Lenovo X1 Extreme 2nd Gen上进行了此操作,这为我提供了足够的读写速度。

我知道它可以变得更快,但我会留一些空间让其他人尝试一下。

线路计数器来源:路德·布利塞特(Luther Blissett)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.