Dosyadan rastgele çizgiler seçme


240

Bir Bash betiğinde, giriş dosyasından ve çıkışından başka bir dosyaya N rastgele çizgi seçmek istiyorum.

Bu nasıl yapılabilir?


Dosyayı rastgele sıralayın ve N ilk satırı seçin.
Piotr Praszmo


31
bu bir kopya değil - N satırına karşı 1 satır istiyor.
OneSolitaryNoob


1
sort -RÖzellikle uzun dosyalar için çok fazla iş yaptığı için katılmıyorum . Sen kullanabilirsiniz $RANDOM, % wc -l, jot, sed -n(à la stackoverflow.com/a/6022431/563329 ) ve bash işlevselliği (diziler, komut yönlendirmeleri, vs) kendi tanımlamak için peekaslında 5.000.000 satırlı dosyalar üzerinde çalışacak işlevi.
isomorphismes

Yanıtlar:


627

Rasgele çizgiler elde etmek için aşağıdaki seçenekle shufbirlikte kullanın :-nN

shuf -n N input > output

2
Sadece rastgele bir sıraya değil, rastgele bir sıraya ihtiyacınız varsa, shuf çok verimsizdir (büyük dosya için): bu cevapta olduğu gibi rezervuar örneklemesi yapmak daha iyidir .
petrelharp

1.000 satır ayıklamak için 500M satır dosya üzerinde bu koştu ve 13 dakika sürdü. Dosyaya aylar içinde erişilmemişti ve bir Amazon EC2 SSD Sürücüsünde.
Jones

yani bu aslında daha sort -Rmı rasgele ?
Mona Jalal

1
@MonaJalal sadece daha hızlı, çünkü satırları karşılaştırmak zorunda değil.
rogerdpack

Sonunda aynı çizgiyi birden fazla verir mi?
Frederick Nord

161

Dosyayı rastgele sıralayın ve ilk 100satırları seçin:

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

43
sortaslında aynı satırları birlikte sıralar, bu nedenle yinelenen satırlarınız varsa ve shuf(bir gnu aracı) yüklediyseniz, bunun için kullanmak daha iyidir.
Kevin

22
Andalso, bu kesinlikle beklemek yapacak çok 80kk hatları - -, oysa, bir ölçüde büyük bir dosya varsa shuf -noldukça anında görür.
Rubens

28
sort -R, Mac OS X (10.9) altında mevcut değildir
Mirko Ebert

3
@ tfb785: sort -Rmuhtemelen GNU seçeneğidir, GNU coreutils'i yükleyin. btw, shufayrıca coreutils'in bir parçasıdır.
jfs

1
@JFSebastian kodu: sort -R input | head -n <num_lines>. Giriş dosyası 279 GB, 2bi + satırlarla. Yine de paylaşamıyorum. Her neyse, nokta, çıktı almak için rastgele seçim yapmak için bazı satırları shuffle ile bellekte tutabilirsiniz . Sıralama, ihtiyaçlarınız ne olursa olsun , tüm dosyayı sıralayacaktır .
Rubens

18

Peki shuf cevabı hakkındaki bir açıklamaya göre bir dakika içinde 78000 000 000 satır karıştırdı.

Meydan okuma kabul edilmiştir...

EDIT: Kendi rekorumu kırdım

powershuf 0.047 saniyede yaptı

$ time ./powershuf.py -n 10 --file lines_78000000000.txt > /dev/null 
./powershuf.py -n 10 --file lines_78000000000.txt > /dev/null  0.02s user 0.01s system 80% cpu 0.047 total

Bu kadar hızlı olmasının nedeni, tüm dosyayı okumadım ve sadece dosya işaretçisini 10 kez hareket ettirin ve işaretçiden sonra satırı yazdırın.

Gitlab Repo

Eski girişim

Önce 78.000.000.000 satırlık bir dosyaya ihtiyacım vardı:

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

Bu bana 78 Milyar satır;

Şimdi shuf kısmı için:

$ 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

Darboğaz CPU'ydu ve birden fazla iş parçacığı kullanmıyordu, 1 çekirdeği% 100'e sabitledi, diğer 15'i kullanılmadı.

Python düzenli olarak kullandığım şey, bu yüzden bunu daha hızlı yapmak için kullanacağım:

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

Bu beni bir dakikadan az bir süre aldı:

$ time ./shuf.py         










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

Bunu, bana bolca okuma ve yazma hızı veren i9 ve Samsung NVMe ile bir Lenovo X1 aşırı 2. nesil üzerinde yaptım.

Daha hızlı olabileceğini biliyorum ama başkalarına denemek için biraz yer bırakacağım.

Satır sayacı kaynağı: Luther Blissett


Peki, powershuf'un iç işleyişi açıklamanıza göre, sadece rastgele görünüyor. Biri 1 karakter uzunluğunda, diğeri 20 karakter uzunluğunda sadece iki satırlı bir dosya kullanarak, her iki satırın da eşit şansla seçilmesini bekliyorum. Programınız için durum böyle değil.
xhienne
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.