मुझे बैश स्क्रिप्ट का उपयोग करके एक विशाल टेक्स्ट फ़ाइल से पहली पंक्ति को बार-बार निकालने की आवश्यकता है।
अभी मैं उपयोग कर रहा हूं sed -i -e "1d" $FILE- लेकिन डिलीट करने में लगभग एक मिनट का समय लगता है।
क्या इसे पूरा करने का एक अधिक कुशल तरीका है?
मुझे बैश स्क्रिप्ट का उपयोग करके एक विशाल टेक्स्ट फ़ाइल से पहली पंक्ति को बार-बार निकालने की आवश्यकता है।
अभी मैं उपयोग कर रहा हूं sed -i -e "1d" $FILE- लेकिन डिलीट करने में लगभग एक मिनट का समय लगता है।
क्या इसे पूरा करने का एक अधिक कुशल तरीका है?
जवाबों:
पूंछ का प्रयास करें :
tail -n +2 "$FILE"
-n x: बस आखिरी xलाइनें प्रिंट करें । tail -n 5आपको इनपुट की अंतिम 5 लाइनें देगा। +उलट के हस्ताक्षर तरह तर्क और मेकअप tailप्रिंट कुछ भी लेकिन पहले x-1लाइनों। tail -n +1पूरी फ़ाइल, tail -n +2सब कुछ लेकिन पहली पंक्ति, आदि को प्रिंट करेगा ।
जीएनयू tailकी तुलना में बहुत तेज है sed। tailबीएसडी पर भी उपलब्ध है और -n +2झंडा दोनों उपकरणों के अनुरूप है। अधिक के लिए FreeBSD या OS X मैन पेज देखें।
बीएसडी संस्करण sedहालांकि की तुलना में बहुत धीमा हो सकता है । मुझे आश्चर्य है कि वे कैसे कामयाब रहे; tailबस एक फ़ाइल लाइन को लाइन से पढ़ना चाहिए, जबकि sedएक स्क्रिप्ट की व्याख्या करने, नियमित अभिव्यक्ति और पसंद को शामिल करने वाले सुंदर जटिल संचालन होते हैं।
नोट: आप का उपयोग करने के लिए परीक्षा हो सकती है
# THIS WILL GIVE YOU AN EMPTY FILE!
tail -n +2 "$FILE" > "$FILE"
लेकिन यह आपको एक खाली फाइल देगा । कारण यह है कि पुनर्निर्देशन ( >) tailशेल द्वारा लागू किए जाने से पहले होता है:
$FILEtailtailप्रक्रिया को रोक देता है$FILEtail अभी खाली से पढ़ता है $FILEयदि आप फ़ाइल के अंदर पहली पंक्ति को हटाना चाहते हैं, तो आपको उपयोग करना चाहिए:
tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
यह &&सुनिश्चित करेगा कि समस्या होने पर फ़ाइल अधिलेखित न हो।
-rविकल्प के साथ BSD 'टेल' का उपयोग करते समय विशिष्ट बफ़र 32k में बदल जाता है। हो सकता है कि सिस्टम में कहीं बफर सेटिंग हो? या -nएक 32-बिट हस्ताक्षरित संख्या है?
tailहोंगी , किसी भी फ़ाइल आकार के लिए काम करेंगी।
-n N means output the last N lines, instead of the last 10; or use +N to output lines starting with the Nth
आप '>' ऑपरेटर का उपयोग किए बिना फ़ाइल को अपडेट करने के लिए -i का उपयोग कर सकते हैं। निम्न आदेश फ़ाइल से पहली पंक्ति को हटा देगा और इसे फ़ाइल में सहेज देगा।
sed -i '1d' filename
unterminated transform source string
sed -i '1,2d' filename
tail -n +2। यकीन नहीं होता कि यह शीर्ष उत्तर क्यों नहीं है।
नहीं, यह उतना ही कुशल है जितना आप प्राप्त करने जा रहे हैं। आप एक सी प्रोग्राम लिख सकते हैं जो काम को थोड़ा तेज (कम स्टार्टअप समय और प्रसंस्करण तर्क) कर सकता है लेकिन यह संभवतः उसी गति की ओर बढ़ेगा जैसे कि फाइलें बड़ी हो जाती हैं (और मुझे लगता है कि वे बड़े हैं अगर यह एक मिनट ले रहा है )।
लेकिन आपका प्रश्न एक ही समस्या से ग्रस्त है, क्योंकि इसमें कई अन्य लोग इस समाधान को पूर्व-दबाते हैं। यदि आप हमें विस्तार से बताना चाहते हैं कि आप क्या करने की कोशिश कर रहे हैं तो कैसे , हम एक बेहतर विकल्प सुझा सकते हैं।
उदाहरण के लिए, यदि यह एक फ़ाइल A है जो कुछ अन्य प्रोग्राम B प्रक्रियाएँ करता है, तो एक समाधान यह होगा कि पहली पंक्ति को अलग न किया जाए, लेकिन इसे अलग तरीके से संसाधित करने के लिए प्रोग्राम B को संशोधित करें।
मान लें कि आपके सभी प्रोग्राम इस फ़ाइल में संलग्न हैं ए और प्रोग्राम बी वर्तमान में इसे हटाने से पहले पहली पंक्ति को पढ़ता है और संसाधित करता है।
आप प्रोग्राम बी को री-इंजीनियर कर सकते हैं ताकि यह पहली पंक्ति को हटाने की कोशिश न करे, लेकिन फ़ाइल A में एक निरंतर (शायद फ़ाइल-आधारित) ऑफसेट को बनाए रखता है ताकि, अगली बार जब यह चलता है, तो यह उस ऑफसेट, प्रक्रिया की तलाश कर सके। वहाँ लाइन, और ऑफसेट अद्यतन।
फिर, एक शांत समय (मध्यरात्रि?) पर, यह वर्तमान में संसाधित सभी लाइनों को हटाने और ऑफसेट को 0 पर सेट करने के लिए फ़ाइल ए की विशेष प्रसंस्करण कर सकता है।
यह निश्चित रूप से एक कार्यक्रम को खोलने और फिर से लिखने के बजाय एक फ़ाइल खोलने और खोजने के लिए तेज़ होगा। यह चर्चा मानती है कि प्रोग्राम बी पर आपका नियंत्रण है। मुझे नहीं पता कि अगर ऐसा है, लेकिन अन्य संभावित समाधान हो सकते हैं यदि आप अधिक जानकारी प्रदान करते हैं।
awk FNR-1 *.csvशायद तेज है।
आप फ़ाइलों को जगह में संपादित कर सकते हैं : बस पर्ल के -iझंडे का उपयोग करें , जैसे:
perl -ni -e 'print unless $. == 1' filename.txt
यह पहली पंक्ति को गायब कर देता है, जैसा कि आप पूछते हैं। पर्ल को पूरी फाइल को पढ़ने और कॉपी करने की आवश्यकता होगी, लेकिन यह आउटपुट को मूल फ़ाइल के नाम से सहेजने की व्यवस्था करता है।
जैसा कि पैक्स ने कहा, आप शायद इससे ज्यादा तेज नहीं लेंगे। कारण यह है कि लगभग कोई फाइल सिस्टम नहीं है जो फ़ाइल की शुरुआत से ट्रंकटिंग का समर्थन करता है इसलिए यह एक ओ ( n) ऑपरेशन होने वाला है जहां nफ़ाइल का आकार है। यद्यपि आप बहुत तेजी से कर सकते हैं, लेकिन बाइट्स की एक ही संख्या (शायद रिक्त स्थान या एक टिप्पणी के साथ) के साथ पहली पंक्ति को अधिलेखित कर सकते हैं जो आपके लिए काम कर सकता है जो आप वास्तव में क्या करने की कोशिश कर रहे हैं (जिस तरह से है?)।
spongeUtil एक अस्थायी फ़ाइल से खेल के लिए जरूरत से बचा जाता है:
tail -n +2 "$FILE" | sponge "$FILE"
spongeवास्तव में स्वीकृत समाधान ( tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE") से अधिक क्लीनर और अधिक मजबूत है
spongeपूरी फाइल को मेमोरी में बफर करता है ? अगर यह सैकड़ों GB का है तो यह काम नहीं करेगा।
spongeसोख कर रख सकते हैं , क्योंकि यह एक / tmp फाइल को इंटरमीडिएट स्टेप के रूप में उपयोग करता है , जिसे बाद में मूल बाद में बदलने के लिए उपयोग किया जाता है।
आप जगह में फ़ाइल को संशोधित करना चाहते हैं, तो आप हमेशा मूल इस्तेमाल कर सकते हैं edअपने के बजाय रों treaming उत्तराधिकारी sed:
ed "$FILE" <<<$'1d\nwq\n'
edआदेश, मूल यूनिक्स पाठ संपादक से पहले वहाँ भी पूर्ण स्क्रीन टर्मिनलों थे, बहुत कम चित्रमय वर्कस्टेशन। exसंपादक, सबसे अच्छा उपयोग कर रहे हैं क्या जब टाइपिंग पेट के शीघ्र में कम से रूप में जाना जाता viहै, एक है पूर्व की जाती थी संस्करण ed, एक ही आदेशों काम के इतने। जबकि edइसका उपयोग अंतःक्रियात्मक रूप से करने के लिए किया जाता है, इसका उपयोग बैच मोड में भी किया जा सकता है, इसके लिए एक स्ट्रिंग भेजकर, जो कि यह समाधान करता है।
अनुक्रम <<<$'1d\nwq\n'लाभ बैश के समर्थन के यहाँ-तार (के लिए ले जाता है <<<) और POSIX उद्धरण ( $'... 'फ़ीड इनपुट करने के लिए करने के लिए) ed: दो पंक्तियों से मिलकर आदेश 1dहै, जो घ eletes लाइन 1 , और फिर wq, जो डब्ल्यू संस्कार फ़ाइल वापस करने के लिए बाहर डिस्क और फिर q संपादन सत्र का उपयोग करता है।
ऐसा करने के लिए विम का उपयोग कर सकते हैं:
vim -u NONE +'1d' +'wq!' /tmp/test.txt
यह तेजी से होना चाहिए, क्योंकि vim प्रक्रिया के दौरान पूरी फ़ाइल नहीं पढ़ेगा।
+wq!अगर आपके खोल को कोसना है तो उद्धृत करने की आवश्यकता हो सकती है। शायद नहीं क्योंकि !एक शब्द की शुरुआत में नहीं है, लेकिन चीजों को उद्धृत करने की आदत में हो रही है शायद चारों ओर अच्छा है। (और यदि आप अनावश्यक रूप से उद्धृत न करके सुपर-दक्षता के लिए जा रहे हैं, तो आपको आसपास के उद्धरणों की आवश्यकता नहीं है 1d।)
Csplit का उपयोग कैसे करें?
man csplit
csplit -k file 1 '{1}'
csplit file /^.*$/1:। या अधिक बस csplit file //1:। या इससे भी अधिक सरल csplit file 2:।
चूंकि ऐसा लगता है कि मैं विलोपन को गति नहीं दे सकता, इसलिए मुझे लगता है कि इस तरह से बैचों में फ़ाइल को संसाधित करने के लिए एक अच्छा तरीका हो सकता है:
While file1 not empty
file2 = head -n1000 file1
process file2
sed -i -e "1000d" file1
end
इसका दोष यह है कि अगर प्रोग्राम बीच में ही मार जाता है (या अगर वहां कुछ खराब सीक्वल है - जिससे "प्रक्रिया" भाग मरने या लॉक-अप करने का कारण बनता है), ऐसी लाइनें होंगी जो या तो छोड़ दी जाती हैं, या दो बार संसाधित होती हैं ।
(file1 में sql कोड की लाइनें शामिल हैं)
क्या N-1 लाइनों पर पूंछ का उपयोग करना और एक फ़ाइल में निर्देश देना, इसके बाद पुरानी फ़ाइल को हटाकर नई फ़ाइल को पुराने नाम पर फिर से काम करना होगा?
यदि मैं यह प्रोग्रामिक रूप से कर रहा था, तो मैं फ़ाइल के माध्यम से पढ़ूंगा, और प्रत्येक पंक्ति को पढ़ने के बाद, फ़ाइल की ऑफसेट याद रखूंगा, इसलिए मैं उस स्थिति में वापस आ सकता हूं जिसमें फ़ाइल को एक कम लाइन के साथ पढ़ा जा सके।