सीड का उपयोग करके बड़ी फ़ाइलों के लिए कुशल इन-प्लेस हेडर निकालना?


24

नीचे दिए गए आदेश मिनट लग सकते हैं फ़ाइल आकार पर निर्भर करता है। क्या कोई और अधिक पवित्र विधि है?

sed -i 1d large_file 

जवाबों:


34

edइसके बजाय कोशिश करें :

ed <<< $'1d\nwq' large_file

यदि उस "बड़े" का अर्थ लगभग 10 मिलियन रेखाएँ या अधिक, बेहतर उपयोग है tail। इन-प्लेस एडिटिंग के लिए सक्षम नहीं है, लेकिन इसका प्रदर्शन उस कमी को क्षम्य बनाता है:

tail -n +2 large_file > large_file.new

कुछ समय अंतर दिखाने के लिए संपादित करें :

( awkकोड द्वारा जयपाल ने एक ही मशीन (CPU 2.2GHz) पर निष्पादन समय जोड़ा है।)

bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped

bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s

bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s

bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s

bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s

bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s

के मामले में tail, मैं नहीं बल्कि समय ऐसा करने के लिए गिनती होगी दोनों पहली पंक्ति को हटा दें और की जगह bigfile.txtके साथ bigfile.new
rozcietrzewiacz

@rozcietrzewiacz, आपकी बात सही है। धन्यवाद। अपडेट किया गया।
14

यह वास्ताव में अच्छा है! मैंने ऐसा ही किया awkऔर निम्न परिणाम प्राप्त हुआ -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
जयपाल सिंह

1
@ जयपाल, मैंने आपका कोड विकल्प की सूची में जोड़ दिया। मेरी मशीन पर यह और भी तेज था। अजीब बात है, मुझे उम्मीद है कि awkप्रदर्शन के करीब होने की उम्मीद है sed। (खुद पर ध्यान दें: कभी भी उम्मीद न करें - इसके बजाय परीक्षण करें।)
मैनटवर्क

मेरे मामले में यह सबसे अच्छा समाधान था: tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;मैं कई प्रक्रियाओं द्वारा उपयोग की गई एकल कार्य सूची का ट्रैक रखने के लिए एक लॉक के साथ एक फ़ाइल का उपयोग कर रहा हूं। मैं क्या प्रारंभिक पोस्टर का इस्तेमाल किया के साथ शुरू: sed -i 1d large_file । जिससे फाइल 1-2 सेकंड के लिए लॉक हो रही थी। tail/mvकॉम्बो लगभग तुरंत पूरा करती है। धन्यवाद!
क्रिस एडम्स

6

फ़ाइल की शुरुआत से चीजों को कुशलतापूर्वक हटाने का कोई तरीका नहीं है। शुरुआत से डेटा हटाने के लिए पूरी फाइल को फिर से लिखना पड़ता है।

किसी फ़ाइल के अंत से छोटा होना बहुत जल्दी हो सकता है (हालांकि OS को केवल फ़ाइल आकार की जानकारी को समायोजित करना होगा, संभवतः अब-अप्रयुक्त ब्लॉकों को साफ़ करना)। यह आम तौर पर संभव नहीं होता है जब आप किसी फ़ाइल के सिर को हटाने की कोशिश करते हैं।

यह सैद्धांतिक रूप से "तेज़" हो सकता है यदि आपने एक संपूर्ण ब्लॉक / सीमा को बिल्कुल हटा दिया है, लेकिन उसके लिए कोई सिस्टम कॉल नहीं है, इसलिए आपको फाइल-सिस्टम-विशिष्ट शब्दार्थ पर भरोसा करना होगा (यदि ऐसा मौजूद है)। (या फ़ाइल की वास्तविक शुरुआत को चिह्नित करने के लिए पहले ब्लॉक / सीमा के अंदर कुछ प्रकार की ऑफ़सेट होती है, मुझे लगता है। ऐसा कभी नहीं सुना गया है।)


यदि फ़ाइल बहुत बड़ी है, तो I / O ओवरहेड लाइनों के अंत को संसाधित करने के लिए आवश्यक सीपीयू ओवरहेड से अधिक (संभवतः बहुत अधिक) होने की संभावना है।
Mat

तुम सही हो। हालाँकि, फ़ाइल सामग्री तक पहुँचने के तरीके में अंतर हो सकता है। आवश्यक नहीं होने पर लाइन द्वारा सबसे अच्छा प्रसंस्करण लाइन नहीं है या आवश्यक नहीं होने पर कम से कम लाइन द्वारा पढ़ने की रेखा नहीं है।
10

2
मुझे आश्चर्य है कि आपके परिणामों में अंतर इतना बड़ा है, और इसे उस फ़ाइल आकार के साथ पुन: उत्पन्न कर सकते हैं। फ़ायदे कम होने लगते हैं क्योंकि फ़ाइल का आकार बढ़ता है (हालांकि सीक 10 एम के साथ, सेड के लिए 15 एस, एड के लिए 5 एस)। वैसे भी अच्छी युक्तियाँ (+1)।
Mat

संस्करण 3.15 से शुरू, लिनक्स में अब कुछ हद तक आधारित फाइल सिस्टम पर एक फ़ाइल के कुछ हिस्सों को हटाने के लिए एपीआई है , लेकिन कम से कम ext4 के लिए जो केवल पूर्ण ब्लॉकों (आमतौर पर 4k) पर किया जा सकता है।
स्टीफन चेज़लस

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

3

सबसे कुशल विधि, यह मत करो! यदि आप करते हैं, तो किसी भी स्थिति में, आपको डिस्क पर दो बार 'बड़े' स्थान की आवश्यकता होती है, और आप आईओ को बर्बाद करते हैं।

यदि आप एक बड़ी फ़ाइल के साथ फंस गए हैं जिसे आप 1 पंक्ति के बिना पढ़ना चाहते हैं, तब तक प्रतीक्षा करें जब तक आपको पहली पंक्ति को हटाने के लिए इसे पढ़ने की आवश्यकता न हो। यदि आपको फ़ाइल को स्टड से प्रोग्राम में भेजने की आवश्यकता है, तो इसे करने के लिए टेल का उपयोग करें:

tail -n +2 | your_program

जब आपको फ़ाइल पढ़ने की आवश्यकता होती है, तो आप पहली पंक्ति को हटाने का अवसर ले सकते हैं, लेकिन केवल तभी जब आपके पास डिस्क पर आवश्यक स्थान हो:

tail -n +2 | tee large_file2 | your_program

यदि आप स्टडिन से नहीं पढ़ सकते हैं, तो एक फीफो का उपयोग करें:

mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line

और भी बेहतर अगर आप बैश का उपयोग कर रहे हैं, तो प्रक्रिया प्रतिस्थापन का लाभ उठाएं:

your_program -i <(tail -n +2 large_file)

यदि आपको फ़ाइल में मांग करने की आवश्यकता है, तो मुझे पहले स्थान पर फ़ाइल के साथ अटकने की तुलना में बेहतर समाधान नहीं दिखता है। यदि यह फ़ाइल stdout द्वारा जनरेट की गई थी:

large_file_generator | tail -n +2 > large_file

वरना, हमेशा पंद्रह या प्रक्रिया प्रतिस्थापन समाधान होता है:

mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file

large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)

1

आप पूर्व मोड में विम का उपयोग कर सकते हैं:

ex -sc '1d|x' large_file
  1. 1 पहली पंक्ति का चयन करें

  2. d हटाना

  3. x सहेजें और बंद करें


0

यह सिर्फ सिद्धांत है, लेकिन ...

एक कस्टम फाइलसिस्टम (जिसे FUSE या इसी तरह के तंत्र का उपयोग करके लागू किया गया है) एक निर्देशिका को उजागर कर सकता है, जिसकी सामग्री कहीं और पहले से मौजूद निर्देशिका के समान है, लेकिन आपकी इच्छानुसार फ़ाइलों को काट दिया गया है। फाइलसिस्टम सभी फाइल ऑफसेट का अनुवाद करेगा। तब आपको किसी फ़ाइल का समय-पुनर्लेखन करने की आवश्यकता नहीं होगी।

लेकिन यह देखते हुए कि यह विचार बहुत ही गैर-तुच्छ है, जब तक कि आपको ऐसी फ़ाइलों के दसियों टेराबाइट्स नहीं मिले हैं, ऐसे फाइलसिस्टम को लागू करना व्यावहारिक होने के लिए बहुत महंगा / समय लेने वाला होगा।

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