Chọn dòng ngẫu nhiên từ một tập tin


239

Trong tập lệnh Bash, tôi muốn chọn N dòng ngẫu nhiên từ tệp đầu vào và xuất sang tệp khác.

Điều này có thể giải quyết như thế nào?


Sắp xếp tệp ngẫu nhiên và chọn N dòng đầu tiên.
Piotr Praszmo


31
đây không phải là một bản sao - anh ta muốn N dòng vs 1 dòng.
OneSol biệtNoob


1
Tôi không đồng ý sort -Rvì nó làm quá nhiều việc, đặc biệt là đối với các tệp dài. Bạn có thể sử dụng $RANDOM, % wc -l, jot, sed -n(à la stackoverflow.com/a/6022431/563329 ), và chức năng bash (mảng, lệnh chuyển hướng, vv) để xác định riêng bạn peekchức năng mà thực sự sẽ chạy trên các tập tin 5.000.000-line.
đẳng cấu

Câu trả lời:


627

Sử dụng shufvới -ntùy chọn như hiển thị bên dưới, để có được Ncác dòng ngẫu nhiên:

shuf -n N input > output

2
Nếu bạn chỉ cần một bộ dòng ngẫu nhiên, không theo thứ tự ngẫu nhiên, thì shuf rất không hiệu quả (đối với tệp lớn): tốt hơn là thực hiện lấy mẫu hồ chứa, như trong câu trả lời này .
petrelharp

Tôi đã chạy tệp này trên tệp hàng 500M để trích xuất 1.000 hàng và mất 13 phút. Tệp đã không được truy cập trong nhiều tháng và trên Ổ SSD Amazon EC2.
T. Brian Jones

Vì vậy, điều này về bản chất là ngẫu nhiên hơn sort -R?
Mona Jalal

1
@MonaJalal không nhanh hơn, vì nó không phải so sánh các dòng.
rogerdpack

Liệu cuối cùng nó có mang lại cùng một dòng nhiều hơn một lần?
Frederick Nord

160

Sắp xếp tệp ngẫu nhiên và chọn 100dòng đầu tiên :

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

43
sortthực sự sắp xếp các dòng giống nhau lại với nhau, vì vậy nếu bạn có thể có các dòng trùng lặp và bạn đã shufcài đặt (một công cụ gnu), tốt hơn là sử dụng nó cho việc này.
Kevin

22
Andalso, điều này chắc chắn sẽ khiến bạn phải chờ đợi rất nhiều nếu bạn có một tệp khổng lồ đáng kể - dòng 80kk -, trong khi đó, shuf -nhoạt động khá tức thời.
Rubens

28
sort -R không khả dụng trong Mac OS X (10.9)
Mirko Ebert

2
@ tfb785: sort -Rcó thể là tùy chọn GNU, cài đặt GNU coreutils. btw, shufcũng là một phần của coreutils.
jfs

1
@JFSebastian Mã : sort -R input | head -n <num_lines>. Tệp đầu vào là 279GB, với 2bi + dòng. Không thể chia sẻ nó, mặc dù. Dù sao, vấn đề là bạn có thể giữ một số dòng trong bộ nhớ với shuffle để thực hiện lựa chọn ngẫu nhiên những gì sẽ xuất. Sắp xếp sẽ sắp xếp toàn bộ tập tin, bất kể nhu cầu của bạn là gì.
Rubens

18

Vâng, theo một nhận xét về câu trả lời của shuf, anh ta đã xáo trộn 78 000 000 000 dòng trong vòng một phút.

Thử thách được chấp nhận ...

Đầu tiên tôi cần một tệp gồm 78.000.000.000 dòng:

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

Điều này mang lại cho tôi một tệp aa với 78 tỷ dòng mới ;-)

Bây giờ cho phần 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

Nút thắt là CPU và không sử dụng nhiều luồng, nó đã ghim 1 lõi với 100% còn lại 15 không được sử dụng.

Python là thứ tôi thường xuyên sử dụng vì vậy đó là thứ tôi sẽ sử dụng để làm cho nó nhanh hơn:

#!/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))

Điều này đã cho tôi chỉ dưới một phút:

$ time ./shuf.py         










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

Tôi đã làm điều này trên Lenovo X1 thế hệ thứ 2 cực mạnh với i9 và Samsung NVMe, cho tôi tốc độ đọc và ghi rất nhiều.

Tôi biết nó có thể nhanh hơn nhưng tôi sẽ rời khỏi một số phòng để thử.

Nguồn truy cập dòng : Luther Blissett

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.