बदलें स्ट्रिंग जिसमें नई फ़ाइल में बड़ी लाइन है


16

किसी को एक गैर-लाइन-आधारित टूल के बारे में पता है जो "बाइनरी" खोज / स्ट्रिंग को कुछ हद तक मेमोरी-कुशल तरीके से बदल देता है? इस प्रश्न को भी देखें ।

मेरे पास एक + 2GB की पाठ फ़ाइल है जिसे मैं वैसा ही प्रोसेस करना चाहूंगा जैसा वह करता है:

sed -e 's/>\n/>/g'

इसका मतलब है, मैं एक के बाद होने वाली सभी नई कहानियों को दूर करना चाहता हूं >, लेकिन कहीं और नहीं, ताकि नियम बाहर हो जाएं tr -d

यह आदेश (जो मुझे एक समान प्रश्न के उत्तर से मिला ) के साथ विफल रहता है couldn't re-allocate memory:

sed --unbuffered ':a;N;$!ba;s/>\n/>/g'

तो, क्या सी का सहारा लिए बिना कोई अन्य तरीके हैं? मैं perl से नफरत करता हूं, लेकिन इस मामले में एक अपवाद बनाने को तैयार हूं :-)

मैं किसी भी ऐसे पात्र के बारे में नहीं जानता, जो डेटा में नहीं होता है, इसलिए \nकिसी अन्य चरित्र के साथ अस्थायी रिप्लेसमेंट कुछ ऐसा है, जो संभव हो तो मैं बचना चाहूंगा।

कोई भी अच्छा विचार, कोई भी?


क्या आपने विकल्प की कोशिश की है --unbuffered?
सीटीएल-एल्ट-डेलोर

--unbufferedस्मृति के साथ या बिना रन के
मैटबायनको

क्या करता $!है?
सीटीएल-अल्ट-डेलोर

पहली sed कमांड में क्या गलत है। लगता है कि दूसरा सब कुछ स्पेस स्पेस में पढ़ रहा है, मुझे नहीं पता कि यह $!है। यह मुझे उम्मीद है कि बहुत सारी मेमोरी की आवश्यकता होगी ।
सीटीएल-एल्ट-डेलोर

समस्या यह है कि sed सब कुछ लाइनों के रूप में पढ़ता है, यही कारण है कि पहली कमांड नईलाइनों को नहीं हटाती है, क्योंकि यह पाठ पंक्ति-दर-पंक्ति फिर से आउटपुट करती है। दूसरा कमांड सिर्फ एक वर्कअराउंड है। मुझे लगता sedहै कि इस मामले में उचित उपकरण नहीं है।
मैटबियानको

जवाबों:


14

यह वास्तव में पर्ल में तुच्छ है, आपको इससे नफरत नहीं करनी चाहिए!

perl -i.bak -pe 's/>\n/>/' file

व्याख्या

  • -i: फ़ाइल को जगह में संपादित करें, और मूल नामक का बैकअप बनाएं file.bak। यदि आप एक बैकअप नहीं चाहते हैं, तो perl -i -peइसके बजाय बस का उपयोग करें ।
  • -pe: इनपुट फाइल लाइन को लाइन से पढ़ें और दिए गए स्क्रिप्ट को लागू करने के बाद प्रत्येक लाइन को प्रिंट करें -e
  • s/>\n/>/: प्रतिस्थापन, बस की तरह sed

और यहाँ एक awkदृष्टिकोण है:

awk  '{if(/>$/){printf "%s",$0}else{print}}' file2 

3
+1। awk गोल्फ:awk '{ORS=/>$/?"":"\n"}1'
ग्लेन जैकमैन

1
मैं सामान्य रूप से पर्ल को नापसंद करता हूं, यही कारण है कि मैंने इस जवाब को चुना (या वास्तव में Gnouc के जवाब के लिए आपकी टिप्पणी) - पठनीयता। एक सरल "sed पैटर्न" के साथ perl -pe का उपयोग करना एक जटिल sed-अभिव्यक्ति की तुलना में अधिक पठनीय है।
मैटबियनको

3
@MattBianco पर्याप्त, लेकिन, बस इतना पता है कि पर्ल के साथ कुछ नहीं करना है। Gnouc ने जो प्रयोग किया है वह कुछ नियमित अभिव्यक्ति भाषाओं (सहित, लेकिन PCREs तक सीमित नहीं है) की विशेषता है, पर्ल की गलती नहीं है। इसके अलावा, ':a;N;$!ba;s/>\n/>/g'आपके प्रश्न में इस सेड मॉन्ट्रोसिटी की विशेषता के बाद , आपने पठनीयता के बारे में शिकायत करने के अपने अधिकार को माफ कर दिया है! : पी
terdon

@glennjackman अच्छा! मैं foo ? bar : bazनिर्माण के साथ खेल रहा था, लेकिन काम करने के लिए नहीं मिला।
terdon

@terdon: हाँ, मेरी गलती है। इसे मिटाओ।
congonglm

7

एक perlसमाधान:

$ perl -pe 's/(?<=>)\n//'

explaination

  • s/// स्ट्रिंग प्रतिस्थापन के लिए प्रयोग किया जाता है।
  • (?<=>) दिखावट पैटर्न है।
  • \n मेल खाता है।

पूरे पैटर्न का मतलब है कि >इससे पहले की सभी नई रूपरेखाओं को हटाना ।


2
टिप्पणी करने के लिए कार्यक्रम के हिस्सों क्या करता है? मैं हमेशा सीखना चाहता हूं।
मैटबियानको

2
लुकबाइंड से परेशान क्यों? सिर्फ क्यों नहीं s/>\n/>/?
terdon

1
या s/>\K\n//काम भी करेगा
ग्लेन जैकमैन

@terdon: बस पहली बात मैं हालांकि, के बजाय हटा
cuonglm

@glennjackman: अच्छी बात!
congonglm

3

इस बारे में कैसा है:

sed ':loop
  />$/ { N
    s/\n//
    b loop
  }' file

GNU sed के लिए, आप प्रश्न के अनुसार -u( --unbuffered) विकल्प जोड़ने का प्रयास कर सकते हैं । GNU सेड भी एक साधारण वन-लाइनर के रूप में खुश है:

sed ':loop />$/ { N; s/\n//; b loop }' file

\nयदि फ़ाइल समाप्त होती है तो यह अंतिम नहीं निकालती है >\n, लेकिन यह संभवत: वैसे भी बेहतर है।
स्टीफन चेजलस

@ स्टीफनचेज़लस, समापन }को एक अलग अभिव्यक्ति में होने की आवश्यकता क्यों है ? क्या यह बहुस्तरीय अभिव्यक्ति के रूप में काम नहीं करेगा?
ग्रीम

1
यह POSIX सेड्स में काम करेगा b loop\n}या -e 'b loop' -e '}'नहीं, लेकिन b loop;}निश्चित रूप से नहीं के रूप में b loop}क्योंकि }और ;लेबल नामों में मान्य हैं (हालांकि उनके सही दिमाग में कोई भी इसका उपयोग नहीं करेगा। और इसका मतलब है कि GNU सेड POSIX अनुरूप नहीं है) और }कमांड को अलग करने की आवश्यकता है। से bआदेश।
स्टीफन चेजलस

@ स्टीफनचेज़ेलस, जीएनयू sedउपरोक्त सभी के साथ भी खुश है --posix! मानक में ब्रेस एक्सप्रेशन के लिए निम्नलिखित भी हैं - The list of sed functions shall be surrounded by braces and separated by <newline>s। क्या इसका मतलब यह नहीं है कि अर्धविराम का उपयोग केवल ब्रेसिज़ के बाहर किया जाना चाहिए?
ग्रीम

@mikeserv, लगातार समाप्त हो रही लाइनों को संभालने के लिए लूप की आवश्यकता होती है >। मूल कभी नहीं था, यह स्टीफन ने बताया था।
ग्रीम

1

आपको कमांड के sedसाथ उपयोग करने में सक्षम होना चाहिए N, लेकिन ट्रिक हर बार पैटर्न स्पेस से एक लाइन को हटाने के लिए होगी जो आप एक और जोड़ते हैं (ताकि पैटर्न स्पेस में हमेशा केवल 2 लगातार लाइनें शामिल हों, इसके बजाय पूरे में पढ़ने की कोशिश करें फ़ाइल) - प्रयास करें

sed ':a;$!N;s/>\n/>/;P;D;ba'

EDIT: पीटरिस क्रुमिन के प्रसिद्ध सेड वन-लाइनर्स को फिर से पढ़ने के बाद मुझे विश्वास है कि एक बेहतर sedसमाधान होगा

sed -e :a -e '/>$/N; s/\n//; ta'

जो केवल इस मामले में निम्नलिखित पंक्ति को जोड़ता है कि यह पहले >से ही अंत में एक मैच बना हुआ है , और लगातार मिलान लाइनों के मामले को संभालने के लिए सशर्त रूप से लूप बैक करना चाहिए (यह क्रुमिन का 39 है। बैकस्लैश के साथ समाप्त होने पर एक पंक्ति को अगले में जोड़ें। "\" बिल्कुल के प्रतिस्थापन के अलावा >के लिए \के रूप में चरित्र शामिल होने, और तथ्य यह है कि में शामिल होने के चरित्र उत्पादन में बनाए रखा जाता है)।


2
यह काम नहीं करता है अगर 2 लगातार लाइनें समाप्त होती हैं >(यह भी जीएनयू विशिष्ट है)
स्टीफन चेज़लस

1

sedअंतिम न्यूलाइन के बिना आउटपुट को उत्सर्जित करने का तरीका प्रदान नहीं करता है। Nमौलिक रूप से काम करने के लिए आपका दृष्टिकोण , लेकिन स्मृति में अधूरी रेखाओं को संग्रहीत करता है, और इस प्रकार विफल हो सकता है यदि लाइनें बहुत लंबी हो जाती हैं (आमतौर पर बहुत लंबी लाइनों को संभालने के लिए sed implentations डिज़ाइन नहीं किए जाते हैं)।

आप इसके बजाय awk का उपयोग कर सकते हैं।

awk '{if (/<$/) printf "%s", $0; else print}'

एक वैकल्पिक दृष्टिकोण tr"बोरिंग", अक्सर-घटने वाले चरित्र के साथ नई लाइन चरित्र को स्वैप करने के लिए उपयोग करना है। अंतरिक्ष यहां काम कर सकता है - एक ऐसा चरित्र चुनें, जो आपके डेटा में प्रत्येक पंक्ति या कम से कम बड़ी संख्या में लाइनों पर दिखाई दे।

tr ' \n' '\n ' | sed 's/> />/g' | tr '\n ' ' \n'

अन्य विधियों में बेहतर प्रभाव के लिए दोनों विधियों को पहले से ही यहां प्रदर्शित किया गया है। और sed2.5gigabyte बफ़र के बिना उसका दृष्टिकोण काम नहीं करता है।
मिकसर्व

क्या किसी ने जिक्र किया? ओह, मैं इसे याद किया, मैं केवल किसी कारण के लिए टेर्डन के जवाब में देखा था। किसी ने भी इस trदृष्टिकोण का उल्लेख नहीं किया - mikeserv, आपने एक अलग (वैध, लेकिन कम सामान्य) दृष्टिकोण पोस्ट किया है जो कि उपयोग करने के लिए भी होता है tr
गिल्स एसओ- बुराई को रोकें '

वैध है, लेकिन मुझे कम जेनेरिक लगता है जैसे आप इसे सिर्फ एक काम, लक्षित समाधान कहते हैं। मुझे लगता है कि यह तर्क देना मुश्किल है कि ऐसा कुछ उपयोगी नहीं है जो कि अजीब है क्योंकि इसमें 0 अपवोट्स हैं। सबसे बड़ा अंतर मैं अपने स्वयं के समाधान और आपकी अधिक सामान्य पेशकश के बीच देख सकता हूं , यह है कि मेरा विशेष रूप से एक समस्या हल करता है, जबकि आपका आम तौर पर हो सकता है। इससे यह सार्थक हो सकता है - और मैं अपना वोट उल्टा भी कर सकता हूं - लेकिन उनके और आपके उत्तरों की पुनरावृत्ति विषय के बीच 7 घंटे की pesky बात भी दूसरों की नकल करती है। क्या आप इसे समझा सकते हैं?
मिकसेर



-1

ऐसा करने के लिए बहुत सारे तरीके हैं, और यहां पर वास्तव में बहुत अच्छे हैं, लेकिन मुझे लगता है कि यह मेरा पसंदीदा है:

tr '>\n' '\n>' | sed 's/^>*//;H;/./!d;x;y/\n>/>\n/'

या और भी:

tr '>\n' '\n>' | sed 's/^>*//' | tr '\n>' '>\n'

मुझे आपका पहला जवाब काम करने के लिए नहीं मिल सकता है। जबकि मैं दूसरे के लालित्य की प्रशंसा करता हूं, मेरा मानना ​​है कि आपको हटाने की आवश्यकता है *। जिस तरह से यह अब है, यह किसी भी खाली लाइनों को एक लाइन के बाद हटा देगा जो एक के साथ समाप्त होता है >। … हम्म। प्रश्न को देखते हुए, मैं देखता हूं कि यह थोड़ा अस्पष्ट है। प्रश्न कहता है, "मैं एक के बाद होने वाली सभी नई सुर्खियों को हटाना चाहता हूं >," मैं व्याख्या करता हूं कि इसका मतलब है कि >\n\n\n\n\nfooइसे बदल दिया जाना चाहिए \n\n\n\nfoo, लेकिन मुझे लगता fooहै कि वांछित आउटपुट हो सकता है।
स्कॉट

@ सच - मैंने निम्नलिखित पर भिन्नताओं के साथ परीक्षण किया: printf '>\n>\n\n>>\n>\n>>>\n>\nf\n\nff\n>\n' | tr '>\n' '\n>' | sed 's/^>*//;H;/./!d;x;y/\n>/>\n/'- >>>>>>>>>>f\n\nff\n\nमेरे लिए इसका परिणाम पहला उत्तर है। मैं उत्सुक हूं कि हालांकि आप इसे तोड़ने के लिए क्या कर रहे हैं, क्योंकि मैं इसे ठीक करना चाहूंगा। दूसरे बिंदु के रूप में - मैं सहमत नहीं हूं कि यह अस्पष्ट है। ओपी हटाने का आग्रह नहीं करता है सभी > पूर्ववर्ती एक \newline, लेकिन इसके बजाय दूर करने के लिए सभी \n ewlines निम्नलिखित एक >
चाटुकार

1
हां, लेकिन एक वैध व्याख्या यह है कि, में >\n\n\n\n\n, केवल पहली न्यूलाइन एक के बाद है >; अन्य सभी अन्य नए समाचारों का अनुसरण कर रहे हैं। ध्यान दें कि ओपी का "यह वही है जो मैं चाहता हूं, अगर यह केवल काम करता है" सुझाव था sed -e 's/>\n/>/g', नहीं sed -e 's/>\n*/>/g'
स्कॉट

1
@ सच - सुझाव काम नहीं किया और कभी नहीं कर सका। मुझे विश्वास नहीं है कि जो व्यक्ति कोड को पूरी तरह से नहीं समझता है, उसके कोड सुझाव को एक व्याख्यात्मक बिंदु के रूप में माना जा सकता है जैसा कि उस व्यक्ति द्वारा उपयोग की जाने वाली सादे भाषा में भी है। और इसके अलावा, आउटपुट - अगर यह वास्तव में काम करता है - s/>\n/>/पर >\n\n\n\n\nअभी भी कुछ ऐसा s/>\n/>/होगा जो संपादित करेगा।
चाटुकार
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.