एक बहुत बड़ी फ़ाइल में तार को प्रतिस्थापित करना


10

मेरे पास बहुत अलग श्रृंखला है जिसमें कोई अलग चरित्र नहीं है, नीचे दिए गए प्रारूप में:

http://example.comhttp://example.nethttp://example.orghttp://etc...

मैं चाहता हूं कि प्रत्येक URL एक नई पंक्ति में हो। मैंने "http: //" के सभी उदाहरणों को "\ nhttp: //" के साथ प्रयोग करके इसे करने की कोशिश की

sed 's_http://_\nhttp://_g' urls.txt

लेकिन एक विभाजन दोष होता है (स्मृति उल्लंघन)। मैं केवल यह बता सकता हूं कि फ़ाइल का सरासर आकार (यह 100GB से अधिक है) सेड कुछ सीमा से अधिक हो रहा है।

मैं फ़ाइल को प्रसंस्करण के लिए कई छोटी फ़ाइलों में विभाजित कर सकता था, लेकिन "http: //" के सभी उदाहरणों को बरकरार रखने की आवश्यकता होगी।

क्या ऐसा करने के लिए इससे अच्छा तरीका है?


मुझे लगता है कि sed 100GB बिना लाइन एंडिंग के पसंद नहीं करता क्योंकि यह अपने बफर में सिंगल लाइन पढ़ने की कोशिश करता है।
jippie

बंटवारा ("कट" होता है) "की परवाह किए बिना", प्रसंस्करण, फिर reassembling हालांकि सही परिणाम देना चाहिए।
enzotib

3
यदि आपके पास वास्तव में एक लंबी लाइन वाली 100GB की टेक्स्ट फाइल है, तो आप काम करने के लिए एक त्वरित C ​​प्रोग्राम लिखना बेहतर समझते हैं।
fpmurphy

जवाबों:


11

साथ awkआप एक बार में पाठ की बड़ी राशि को पढ़ने से बचने कर सकते हैं:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt

सफलता उपयोग किए गए awkकार्यान्वयन पर निर्भर हो सकती है। उदाहरण के लिए gawkठीक काम करता है, लेकिन mawkदुर्घटनाओं।


6

यह काम करेगा:

perl -pe 'BEGIN { $/ = "//" } s!(?=http://\z)!\n!' urls.txt

$ / सेट करके , मैंने एक पंक्ति की परिभाषा बदल दी है ताकि यह //एक नई पंक्ति के बजाय समाप्त हो जाए । यह पर्ल को एक बार में एक URL पढ़ा देता है। यह संभावना नहीं है कि //इस योजना के बाद एक URL शामिल है , लेकिन यह ठीक है अगर कोई करता है, तो रेगेक्स इसे नई नई कहानियों को जोड़ने से रखेगा।

यदि आप पहले URL से पहले एक रिक्त रेखा जोड़ने से बचना चाहते हैं:

perl -pe 'BEGIN { $/ = "//"; print scalar <> } s!(?=http://\z)!\n!' urls.txt

आप यह देखने के लिए बेंचमार्किंग की कोशिश कर सकते हैं कि क्या s!http://\z!\nhttp://!यह तेज है। वे बराबर हैं। ध्यान दें कि /gध्वज प्रतिस्थापन पर आवश्यक नहीं है, क्योंकि "लाइन" प्रति केवल एक मैच हो सकता है।


क्या बहु-गीगाबाइट-लंबी लाइनों के साथ पर्ल रेगेक्सप इंजन ठीक है?
एलेक्सियोस

2
@ एलेक्सियो, शायद नहीं, लेकिन यह होने की आवश्यकता नहीं है। जब से मैं बदला हूं $/, यह केवल एक समय में एक URL के साथ काम करेगा।
cjm

आह, मैं देख रहा हूं कि आपने वहां क्या किया। यह 90 के दशक के बाद से है, और मुझे करना था man perlvar, लेकिन यह इस तरह से समझ में आता है।
एलेक्सिओस

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

@ हाँ, मैं http:regex में भाग के लिए परीक्षण कर रहा हूँ । यह हर जांच करेगा //, लेकिन यह एक नई पंक्ति नहीं जोड़ेगा जब तक कि यह न मिले http://
cjm

5
  1. :एक नई लाइन के साथ सभी घटनाओं को बदलें , फ़ाइल को काट दें।
  2. बदलने के
    • http रेखा के अंत में
    • इसके बाद एक नई http:पंक्ति और इसके आगे की पंक्ति को जोड़ा जाएगा
  3. एक बार दोहराएं, इसलिए भी और विषम लाइनें अपडेट की जाती हैं

ये चरण इस तरह दिखते हैं:

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. जांचें कि क्या ऐसी रेखाएं हैं जो शुरू नहीं होती हैं http://, रेखा संख्याओं को प्रिंट करें। यह तभी होगा जब a: URL में कहीं और के बाद है http

    grep -nv '^http://'

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