टेक्स्ट को बहुत बड़ी फ़ाइल में जल्दी से बदलें


25

मेरे पास 25GB टेक्स्ट फ़ाइल है जिसे केवल कुछ लाइनों पर प्रतिस्थापित स्ट्रिंग की आवश्यकता है। मैं sedसफलतापूर्वक उपयोग कर सकता हूं लेकिन इसे चलाने में वास्तव में लंबा समय लगता है।

sed -i 's|old text|new text|g' gigantic_file.sql

क्या ऐसा करने का कोई तेज़ तरीका है?


क्या आप जानते हैं कि लाइन नंबर कहाँ पाठ को बदलना है? यदि इसे तेज करने के लिए आपका एकमात्र विकल्प तेज कंप्यूटर नहीं है। तथ्य यह है कि आपके पास बड़ी मात्रा में डेटा है इसका मतलब है कि इसके माध्यम से खोज करने में बड़ी मात्रा में समय लगेगा।
डेविड किंग

मैं बहुत जल्दी लाइन नंबर के लिए grep कर सकता हूं, इसलिए हां।
22

आप इसे तेज करने के लिए कई CPU कोर का उपयोग भी कर सकते हैं - रैंकफोकस.com
use

बड़ी फ़ाइलों के लिए sed का उपयोग न करें। पर एक नजर डालें vi या विम बजाय।
माइक जेरामेसी 56

जवाबों:


26

तुम कोशिश कर सकते हो:

sed -i '/old text/ s//new text/g' gigantic_file.sql

इस रेफ से :

स्पीड के लिए ऑप्टिमाइज़िंग: यदि निष्पादन की गति को बढ़ाने की आवश्यकता है (बड़ी इनपुट फ़ाइलों या धीमी प्रोसेसर या हार्ड डिस्क के कारण), तो प्रतिस्थापन को अधिक तेज़ी से निष्पादित किया जाएगा यदि "s /.../ देने से पहले" खोज "अभिव्यक्ति निर्दिष्ट है। ../ ”निर्देश।

यहाँ 10G फ़ाइल की तुलना है। पहले:

$ time sed -i 's/original/ketan/g' wiki10gb
real    5m14.823s
user    1m42.732s
sys     1m51.123s

बाद:

$ time sed -i '/ketan/ s//original/g' wiki10gb
real    4m33.141s
user    1m20.940s
sys     1m44.451s

आखिरी sedको गलत तरीके से याद किया जाता है। मैंने पिछली sedकमांड को ठीक करने के लिए कल इस पोस्ट को संपादित किया जो होना चाहिए time sed -i '/original/ s//ketan/g' wiki10gbऔर नहीं time sed -i '/ketan/ s//original/g' wiki10gb। मैं आज अपना संपादन पुनः प्राप्त कर रहा हूं क्योंकि 1. बार अब आदेश से मेल नहीं खाता है और मैंने 3+ जीबी फ़ाइल पर GNU sed के साथ एक ही परीक्षण किया है और मैं दोनों sedविकल्पों के बीच कोई अंतर नहीं देखता हूं । मुझे संदेह है कि समय में अंतर गलत वर्तनी के कारण है।
xhienne

@xhienne मुझे यकीन नहीं है कि आपको गलत वर्तनी से क्या मतलब है। पहले भाग में, मैं 'केतन' के साथ 'मूल' शब्द का प्रतिस्थापन कर रहा हूँ और दूसरे में मैं 'केतन' शब्द को 'मूल' के साथ प्रतिस्थापित कर रहा हूँ, जिसके परिणामस्वरूप या तो मामले में समान संख्या में प्रतिस्थापन होते हैं।
एमके

1
मैं एक नए उपयोगकर्ता द्वारा "प्रतिष्ठा" लागू कर रहा था जिसमें पर्याप्त प्रतिष्ठा नहीं थी। अब मुझे समझ में आया कि आपने क्या किया। हालाँकि, यदि आप यह साबित करना चाहते हैं कि एक वाक्यविन्यास एक दूसरे से बेहतर है, तो आपको ठीक वही ऑपरेशन करना होगा जो यहाँ नहीं है (CPU-wise, 5-char string की तलाश वही है जो किसी की तलाश में नहीं है 7-चार तार)। इसके अलावा, 10GB फ़ाइल पर इस तरह का परीक्षण आपके मशीन लोड (CPU, डिस्क) पर बहुत निर्भर करता है। मैंने timeव्यक्तिगत रूप से परिणामों में बहुत उतार-चढ़ाव देखे , लेकिन सभी में, समय में कोई अंतर नहीं था।

मेरा मानना ​​है कि यह संबंधित है - यहां स्वीकृत उत्तर देखें, stackoverflow.com/questions/11145270/… >> sed पूरी फाइल को स्ट्रीम करता है, लेकिन जैसा कि इस उत्तर में उल्लेख किया गया है, लाइन नंबर (यदि ज्ञात हो) निर्दिष्ट करने से मदद मिलती है: मेरे मामले में , निष्पादन की गति में ~ 2 गुना वृद्धि (GNU sed 4.5)। आप पैटर्न खोज के आधार पर लाइन नंबर खोजने के लिए grep -n या ripgrep (rg) कर सकते हैं। वास्तव में, लाइन संख्या को निर्दिष्ट करना उस फ़ाइल पर एक खोज परिणाम होने जैसा है, ऊपर दिए गए उत्तर के अनुसार।
विक्टोरिया स्टुअर्ट

1

संक्षिप्त उत्तर "नहीं" है - इस तरह के ऑपरेशन पर आपका सीमित कारक डिस्क IO है। 25GB डिस्क को किसी भी तेजी से स्ट्रीम करने का कोई तरीका नहीं है। यदि आप संपादन नहीं करते हैं, तो आप एक मामूली सुधार प्राप्त कर सकते हैं, और आप sedएक अलग ड्राइव का परिणाम लिखते हैं (यदि आपके पास एक उपलब्ध है) - क्योंकि इस तरह से आप एक से पढ़ सकते हैं, जबकि दूसरे से लिख सकते हैं और थोड़ा-बहुत लिख सकते हैं परिणामस्वरूप कम विवाद।

आप प्रत्येक लाइन के लिए रेगेक्स इंजन का उपयोग न करके इसे थोड़ा गति देने में सक्षम हो सकते हैं - इसलिए उदाहरण के लिए पर्ल का उपयोग करना (मुझे पूरा यकीन है कि आप ऐसा कर सकते हैं sedलेकिन मुझे सिंटैक्स नहीं पता है) - यह इस से शुरू होगा लाइन 10,000 बाद में।

perl -pe '$. > 10_000 && s/old_text/new_text/g' 

और अगर आरई (मेटाचैकर) में किसी भी प्रकार की जटिलताएं हैं, तो उन को कम करने से रेगेक्स इंजन की दक्षता में थोड़ा सुधार होगा ।


1
sed -i '10000,$ s/old_text/new_text/g'
तलछट में

लवली। मुझे नहीं पता कि sedतुलना कैसे की जाती है - मैं थोड़ी तेजी से मानती हूं, लेकिन फ़ाइल आकार के कारण बहुत अधिक नहीं।
Sobrique

मुझे लगता है कि perl sed की तुलना में तेज़ है, लेकिन sed कुछ हद तक कम गूढ़ है, या इसके लिए प्रारंभिक सीखने की अवस्था में कम की आवश्यकता होती है।
दानी_ल

1
देखें, अब मैंने कहा होगा कि आप - (लगभग) में लिख सकते sedहैं perl, लेकिन उत्तरार्द्ध आपको और अधिक वर्बोज़ स्क्रिप्ट भी लिखने देता है।
सोब्रीक

0

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

नोट: यह मुश्किल है और इसमें कस्टम कोड लिखना शामिल है।

यदि आप C या C ++ में काम कर रहे हैं, या सिस्टम कॉल और लिखने के लिए अपनी पसंदीदा भाषा के रैपर में fseek के लिए मैन पेज देखें।

यदि आप केवल कमांड लाइन का उपयोग करने पर जोर देते हैं, और आप पाठ के बाइट्स प्राप्त कर सकते हैं, तो आप प्रतिस्थापन पाठ को ध्यान से "dd" कमांड के साथ लिख सकते हैं।

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