विशाल पाठ फ़ाइल पर 'सिर' या 'पूंछ' का उपयोग करना - 19 जीबी


15

मुझे एक बहुत बड़ी पाठ फ़ाइल के विखंडू को देखने में समस्या है। लगभग 19 GB की यह फ़ाइल, स्पष्ट रूप से किसी भी पारंपरिक माध्यम से देखने के लिए बहुत बड़ी है।

मैंने कोशिश की है head 1और tail 1( head -n 1और tail -n 1) दोनों आज्ञाओं के साथ विभिन्न तरीकों से (बीच में एक टुकड़े पर पाने के लिए) बिना किसी भाग्य के साथ। उबंटू 9.10 पर चलने वाली मेरी लिनक्स मशीन इस फाइल को प्रोसेस नहीं कर सकती है।

मैं इस फ़ाइल को कैसे संभालूँ? मेरा अंतिम लक्ष्य 45000000 और 45000100 लाइनों पर सान करना है।


एक त्वरित पायथन स्क्रिप्ट लिखने के बारे में सोचने के लिए जो लाइनों को पढ़ती है और जिन्हें मुझे फाइल करने की आवश्यकता होती है, उन्हें प्रिंट करता हूं, लेकिन मैं यह कल्पना कर सकता हूं कि लंबे समय तक ...
निकोलेरियस

क्या सभी रेखाएँ समान लंबाई हैं?
पॉल

@Paul - दुर्भाग्य से, वे समान लंबाई नहीं हैं।
निकरेलियस

आप splitकाम करने के लिए बड़ी फ़ाइल को आसान बनाने की कोशिश कर सकते हैं ।
iglvzx

1
ठीक है। किसी फ़ाइल की कोई भी प्रोसेसिंग जिसमें बड़ा समय लगेगा, इसलिए नीचे दिए गए उत्तर मदद करेंगे। यदि आप केवल उस भाग को निकालना चाहते हैं जिसे आप ढूंढ रहे हैं और लगभग अनुमान लगा सकते हैं कि यह वह जगह है जहां आप ddउस बिट का उपयोग कर सकते हैं जिसे आप बाद में कर रहे हैं। उदाहरण के लिए dd if=bigfile of=extractfile bs=1M skip=10240 count=510GB बिंदु से शुरू होने वाली फ़ाइल से 5MB निकालेगा।
पॉल

जवाबों:


11

आपको उपयोग करना चाहिए sed

sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines

यह sed45000000-45000100 समावेशी लाइनों को प्रिंट करना और लाइन 45000101 पर छोड़ना बताता है।


1
यह अभी भी बहुत धीमा है, लगभग सिर की तरह -45000000,45000100p bigfile | टेल -100> सेवलाइन
दिमित्री

tail+|headएक अच्छा 10-15% से तेज है।
एरच

4

एक एकल तालिका के साथ एक MySQL डेटाबेस बनाएं जिसमें एक एकल फ़ील्ड है। फिर अपनी फ़ाइल को डेटाबेस में आयात करें। इससे एक निश्चित रेखा को देखना बहुत आसान हो जाएगा।

मुझे नहीं लगता कि कुछ और तेजी से हो सकता है (यदि headऔर tailपहले से ही विफल हो)। अंत में, एप्लिकेशन जो लाइन ढूंढना चाहता है nउसे पूरी फाइल के माध्यम से तलाश करना पड़ता है जब तक कि nनई सुचना नहीं मिल जाती । कुछ प्रकार के लुकअप (लाइन-इंडेक्स को बाइट ऑफ़सेट इन फाइल) के बिना कोई बेहतर प्रदर्शन हासिल नहीं किया जा सकता है।

यह देखते हुए कि MySQL डेटाबेस बनाना और उसमें डेटा आयात करना कितना आसान है, मुझे लगता है कि यह एक व्यवहार्य दृष्टिकोण है।

यहां है कि इसे कैसे करना है:

DROP DATABASE IF EXISTS helperDb;
CREATE DATABASE `helperDb`;
CREATE TABLE `helperDb`.`helperTable`( `lineIndex` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `lineContent` MEDIUMTEXT , PRIMARY KEY (`lineIndex`) );
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable (lineContent);
SELECT lineContent FROM helperTable WHERE ( lineIndex > 45000000 AND lineIndex < 45000100 );

/tmp/my_large_file वह फ़ाइल होगी जिसे आप पढ़ना चाहते हैं।

प्रत्येक पंक्ति पर टैब-सीमांकित मानों के साथ फ़ाइल आयात करने का सही सिंटैक्स है:

LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable FIELDS TERMINATED BY '\n' (lineContent);

इसका एक और बड़ा फायदा यह है कि यदि आप बाद में लाइनों के दूसरे सेट को निकालने का निर्णय लेते हैं, तो आपको फिर से प्रसंस्करण के लिए घंटों इंतजार नहीं करना होगा (जब तक कि आप निश्चित रूप से डेटाबेस को हटा नहीं देते)।


तो यह एक अच्छा समाधान है, वास्तव में। मुझे यह sedनीचे दिए गए आदेश के साथ काम करने के लिए मिला , और मेरी रेखाओं को पहचान लिया। लेकिन अब मेरे पास एक अनुवर्ती सवाल है कि डेटाबेस विधि के लिए बेहतर अनुकूल हो सकता है। अब मुझे फ़ाइल से कुछ सौ लाइनें हटाने की आवश्यकता है।
निकोलसियस

मुझे यकीन है कि sedवह भी कर सकता है। बेशक, यदि आपके पास डेटाबेस में डेटा था, तो यह एक तुच्छ फ़ाइल होगी जिसे आप चाहते हैं बस लाइनों के साथ एक नई फ़ाइल निर्यात करें।
डेर होच्स्टापलर

एक बार फिर धन्यवाद। मैंने इसका sedउत्तर लिया (क्योंकि इससे मुझे अधिक तात्कालिक खुशी मिली; -) लेकिन आपने आपको वोट दिया क्योंकि मैं भविष्य में आपकी पद्धति का उपयोग करूंगा। मैं इसकी सराहना करता हूं।
निकोलसियस

1
तुम एक जोड़ने की कोशिश कर सकते FIELDS TERMINATED BY '\n'करने के लिए LOAD DATAलाइन।
डेर होकस्टापलर

1
मुझे क्षमा करें, मेरे कोड में एक गलती थी। मैंने आपके मामले के लिए सही सिंटैक्स भी जोड़ा (इस बार परीक्षण किया गया)।
डेर होकस्टाप्लर

1

बड़ी फ़ाइलों के लिए दो अच्छे पुराने उपकरण हैं joinऔर split। आप --lines=<number>उस विकल्प के साथ विभाजन का उपयोग कर सकते हैं जो फ़ाइल को निश्चित आकार की कई फ़ाइलों में काटता है।

उदाहरण के लिए split --lines=45000000 huge_file.txt। परिणामी भाग xa, xb आदि में होंगे। फिर आप वह headभाग xb कर सकते हैं , जिसमें वे पंक्तियाँ शामिल होंगी जो आप चाहते थे। आप एकल बड़ी फ़ाइल पर फ़ाइलों को 'जॉइन' भी कर सकते हैं।


बहुत बढ़िया, धन्यवाद, मैं पूरी तरह से विभाजन आदेश के बारे में भूल गया।
सिलिकॉनक्रॉस्ट

0

आपके पास सही उपकरण हैं लेकिन उनका गलत तरीके से उपयोग कर रहे हैं। जैसा कि पहले U & L पर उत्तर दिया गया था, tail -n +X file | head -n Y(ध्यान दें +) sedX पर शुरू होने वाली Y लाइनों की तुलना में 10-15% अधिक तेज है। और सुविधाजनक रूप से, आपको स्पष्ट रूप से exitइस प्रक्रिया को करने की आवश्यकता नहीं है sed

टेल पहले X-1 लाइनों को पढ़ेगा और छोड़ देगा (इसके आसपास कोई रास्ता नहीं है), फिर निम्न पंक्तियों को पढ़ें और प्रिंट करें। हेड पढ़े गए लाइनों की संख्या को पढ़ेगा और प्रिंट करेगा, फिर बाहर निकल जाएगा। जब सिर बाहर निकलता है, तो पूंछ एक SIGPIPE सिग्नल प्राप्त करती है और मर जाती है, इसलिए यह इनपुट फ़ाइल से लाइनों के बफर आकार (आमतौर पर कुछ किलोबाइट) से अधिक नहीं पढ़ेगी।

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