एक फ़ाइल से यादृच्छिक लाइनों का चयन करें


240

एक बैश स्क्रिप्ट में, मैं इनपुट फ़ाइल और आउटपुट से एन यादृच्छिक लाइनों को किसी अन्य फ़ाइल में चुनना चाहता हूं।

यह कैसे किया जा सकता है?


फ़ाइल को बेतरतीब ढंग से सॉर्ट करें और एन पहली लाइनें चुनें।
पियोट्र्स प्रेज़मो

इसके अलावा stackoverflow.com/questions/12354659/… देखें ।
एक्यूमेनस

31
यह डुप्लिकेट नहीं है - वह एन लाइन्स बनाम 1 लाइन चाहता है।
OneSolitaryNoob


1
मैं इससे असहमत हूं sort -Rक्योंकि यह बहुत अधिक काम करता है, खासकर लंबी फाइलों के लिए। आप उपयोग कर सकते हैं $RANDOM, % wc -l, jot, sed -n(ला à stackoverflow.com/a/6022431/563329 ), और बैश कार्यक्षमता (सरणियों, आदेश रीडायरेक्ट, आदि) अपनी खुद की परिभाषित करने के लिए peekसमारोह जो वास्तव में 5,000,000 लाइन फ़ाइलों पर चलेंगे।
isomorphismes

जवाबों:


627

यादृच्छिक लाइनों को प्राप्त करने के लिए नीचे दिखाए गए विकल्प के shufसाथ प्रयोग करें :-nN

shuf -n N input > output

2
यदि आपको बस एक यादृच्छिक क्रम में लाइनों की एक यादृच्छिक सेट की आवश्यकता है, तो शफ बहुत अक्षम (बड़ी फ़ाइल के लिए) है: बेहतर है कि जलाशय का नमूना करना है, जैसा कि इस उत्तर में है
पेट्रेलर्प

मैंने 1000 पंक्तियों को निकालने के लिए 500M पंक्ति की फ़ाइल पर इसे चलाया और इसमें 13 मिनट लगे। फ़ाइल महीनों में एक्सेस नहीं की गई थी, और अमेज़न EC2 SSD ड्राइव पर है।
टी। ब्रायन जोन्स

तो यह सार में अधिक यादृच्छिक है कि sort -R?
मोना जलाल

1
@MonaJalal बस तेजी से, क्योंकि यह लाइनों की तुलना बिल्कुल नहीं है।
रोजरपैक

क्या यह अंततः एक ही लाइन को एक से अधिक बार प्राप्त करता है?
फ्रेडरिक नॉर्ड

161

फ़ाइल को क्रमबद्ध रूप से क्रमबद्ध करें और पहली 100पंक्तियाँ चुनें:

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

43
sortवास्तव में समान लाइनों को एक साथ shufक्रमबद्ध करता है , इसलिए यदि आपके पास डुप्लिकेट लाइनें हो सकती हैं और आपके पास (एक ग्नू उपकरण) स्थापित है, तो इसके लिए इसका उपयोग करना बेहतर है।
केविन

22
अंदलो, यह निश्चित रूप से आपको बहुत इंतजार करने वाला है यदि आपके पास एक बहुत बड़ी फ़ाइल है - 80kk लाइनें -, जबकि, shuf -nकाफी तात्कालिक रूप से कार्य करता है।
रुबेंस

28
सॉर्ट -R मैक ओएस एक्स (10.9) के तहत उपलब्ध नहीं है
मिरको एबर्ट

2
@ tfb785: sort -Rशायद GNU विकल्प है, GNU कोरुटिल्स स्थापित करें। btw, shufकोरयूटिल्स का भी हिस्सा है।
jfs

1
@JFSebastian कोड sort -R input | head -n <num_lines>:। 2 जीबी + लाइनों के साथ इनपुट फ़ाइल 279GB थी। हालांकि, इसे साझा नहीं कर सकते। वैसे भी, मुद्दा यह है कि क्या उत्पादन करने के लिए यादृच्छिक चयन करने के लिए फेरबदल के साथ स्मृति में कुछ लाइनें रख सकते हैं । आपकी आवश्यकताओं की परवाह किए बिना, संपूर्ण फ़ाइल को क्रमबद्ध करने जा रहा है ।
रूबेंस

18

खैर शफ जवाब पर एक टिप्पणी के अनुसार उन्होंने एक मिनट के भीतर 78 000 000 000 लाइनों को हिला दिया।

चुनौती स्वीकार की गई...

पहले मुझे 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

यह मुझे 78 बिलियन के नए अंक के साथ एक फाइल देता है ;-)

अब शफ भाग के लिए:

$ 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

अड़चन सीपीयू थी और कई थ्रेड्स का उपयोग नहीं कर रहा था, यह 1 कोर को 100% पर पिन करता था अन्य 15 का उपयोग नहीं किया गया था।

अजगर वह है जो मैं नियमित रूप से उपयोग करता हूं, इसलिए मैं इसे तेजी से बनाने के लिए उपयोग करूंगा:

#!/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 और सैमसंग NVMe के साथ लेनोवो X1 एक्सट्रीम 2 जीएन पर ऐसा किया, जो मुझे पढ़ने और लिखने की गति प्रदान करता है।

मुझे पता है कि यह तेज़ हो सकता है लेकिन मैं दूसरों को आज़माने के लिए कुछ जगह छोड़ दूँगा।

लाइन काउंटर स्रोत: लूथर ब्लिसटेट

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.