मैं तुम्हारे साथ सहमत होगा - यह शायद है एक सामान्य समस्या है। कुछ सामान्य उपयोगिताओं में इसे संभालने के लिए कुछ सुविधाएं हैं, हालांकि।
nl
nlउदाहरण के लिए, में इनपुट को अलग करती है तार्किक पृष्ठों के रूप में -dएक दो चरित्र द्वारा elimited खंड सीमांकक । अकेले एक लाइन पर तीन घटनाएँ एक हेडिंग , दो बॉडी और एक पाद की शुरुआत का संकेत देती हैं । यह आउटपुट में एक रिक्त लाइन के साथ इनपुट में पाए गए इनमें से किसी को भी बदल देता है - जो केवल रिक्त लाइनें हैं जो यह कभी प्रिंट करता है
मैंने आपके उदाहरण को बदलकर एक और अनुभाग शामिल किया और इसे अंदर डाल दिया ./infile। तो यह इस तरह दिखता है:
line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
@@start
line M
line N
line O
@@end
फिर मैंने निम्नलिखित भाग किया:
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end$/@@/' <infile |
nl -d@@ -ha -bn -w1
nlकहा जा सकता है कि तार्किक पृष्ठों पर राज्य जमा कर सकते हैं , लेकिन यह डिफ़ॉल्ट रूप से नहीं होता है। इसके बजाय यह शैलियों के अनुसार , और अनुभाग द्वारा इसके इनपुट की पंक्तियों को संख्या देगा । तो -haइसका मतलब है कि सभी हेडर लाइन्स और बॉडी लाइन्स-bn का कोई मतलब नहीं है - जैसा कि बॉडी स्टेट में शुरू होता है ।
जब तक मैंने यह नहीं सीखा, तब तक मैं nlकिसी भी इनपुट के लिए उपयोग करता था, लेकिन यह समझने के बाद कि nlइसके डिफॉल्ट -dएलिमिटर के अनुसार आउटपुट विकृत हो सकता है, \:मैंने इसके साथ अधिक सावधान रहना सीखा और grep -nF ''इसके बजाय अनटाइटेड इनपुट का उपयोग करना शुरू कर दिया । लेकिन उस दिन एक और सबक सीखा गया था कि nlइसे अन्य मामलों में बहुत उपयोगी रूप से लागू किया जा सकता है - जैसे कि यह एक - यदि आप केवल इसके इनपुट को थोड़ा संशोधित करते हैं - जैसा कि मैं sedऊपर करता हूं ।
आउटपुट
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
यहाँ कुछ और के बारे में है nl- क्या आप ऊपर सभी रेखाओं को देखते हैं लेकिन गिने हुए स्थान रिक्त स्थान से शुरू होते हैं? जब nlसंख्याएँ रेखाएँ होती हैं तो यह प्रत्येक के सिर में एक निश्चित संख्या में वर्ण सम्मिलित करती है। उन पंक्तियों के लिए यह संख्या नहीं है - यहां तक कि रिक्त - यह हमेशा -wअनिर्दिष्ट -sलाइनों के सिर पर ( idth count + eparator len) * रिक्त स्थान डालकर इंडेंट से मेल खाता है । यह आपको गिने-चुने सामग्री को पुन: क्रमांकित सामग्री की तुलना करके - और थोड़े प्रयास से पुन: प्रस्तुत करने की अनुमति देता है। जब आप विचार करते हैं कि nlइसके इनपुट को आपके लिए तार्किक खंडों में विभाजित किया जाएगा, और यह कि आप -sप्रत्येक पंक्ति के शीर्ष पर मनमाना ट्रिंग्स सम्मिलित कर सकते हैं , तो यह अपने आउटपुट को संभालने में बहुत आसान हो जाता है:
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end/@@/; t
s/^\(@@\)\{1,3\}$/& /' <infile |
nl -d@@ -ha -bn -s' do something with the next line!
'
उपरोक्त प्रिंट ...
line A
line B
1 do something with the next line!
line X
2 do something with the next line!
line Y
3 do something with the next line!
line Z
line C
line D
1 do something with the next line!
line M
2 do something with the next line!
line N
3 do something with the next line!
line O
जीएनयू sed
यदि nlआपका लक्ष्य एप्लिकेशन नहीं है, तो एक मैच के आधार पर एक GNU आपके लिए एक मनमाना शेल कमांड xecute sedकर सकता है e।
sed '/^@@.*start$/!b
s//nl <<\\@@/;:l;N
s/\(\n@@\)[^\n]*end$/\1/
Tl;e' <infile
ऊपर sedपैटर्न स्पेस में इनपुट एकत्र करता है जब तक कि यह प्रतिस्थापन Tस्थापन को सफलतापूर्वक पारित करने और हाबिल bको वापस रोकना पर्याप्त नहीं है :l। जब ऐसा होता है, तो यह इनपुट के साथ executes का nlप्रतिनिधित्व करता है, <<यहां इसके बाकी सभी पैटर्न-स्पेस के लिए दस्तावेज़ के रूप में दर्शाया गया है।
वर्कफ़्लो इस तरह है:
/^@@.*start$/!b
- अगर एक
^पूरी पंक्ति $है !नहीं /से मेल /ऊपर पैटर्न, तो यह है bस्क्रिप्ट से बाहर ranched और autoprinted - तो इस बिंदु से पर हम केवल जो पैटर्न के साथ शुरू हुआ लाइनों की एक श्रृंखला के साथ काम कर रहे हैं।
s//nl <<\\@@/
- खाली
s//फ़ील्ड मिलान के /लिए अंतिम पते के लिए खड़ा है sed- इसलिए यह कमांड इसके बजाय पूरी @@.*startलाइन को प्रतिस्थापित करता है nl <<\\@@।
:l;N
:आदेश एक शाखा लेबल को परिभाषित करता है - यहाँ मैं एक का नाम सेट :lहाबिल। NExt आदेश अगले एक के बाद पैटर्न अंतरिक्ष के लिए इनपुट की रेखा भी संलग्न \newline चरित्र। यह \nएक sedपैटर्न स्पेस में ewline प्राप्त करने के लिए केवल कुछ तरीकों में से एक है - \newline वर्ण एक व्युत्पन्न के लिए एक निश्चित सीमांकक है sedजो इसे थोड़ी देर कर रहा है।
s/\(\n@@\)[^\n]*end$/\1/
s///एक शुरुआत के बाद और केवल एक अंतिम पंक्ति की पहली घटना के बाद ही यह ubstration सफल हो सकता है । यह केवल एक पैटर्न स्पेस पर कार्य करेगा जिसमें पैटर्न स्पेस के बहुत अंत को चिह्नित करते हुए \nतुरंत अंतिम ईवलाइन का पालन किया जाता है। जब यह कार्य करता है, तो यह पूरे मिलान वाले स्ट्रिंग को पहले समूह के साथ बदल देता है , या ।@@.*end$\1\(\)\n@@
Tl
Tकिसी लेबल की स्था आदेश शाखाओं (यदि उपलब्ध) अगर एक सफल प्रतिस्थापन पिछली बार एक इनपुट लाइन पैटर्न अंतरिक्ष में खींचा गया था के बाद से नहीं हुआ (मैं w / कर के रूप में N) । इसका मतलब यह है कि हर बार एक \nईवालाइन को पैटर्न स्पेस से जोड़ा जाता है जो आपके अंतिम सीमांकक से मेल नहीं खाता है, एस्ट्रल Tकमांड विफल रहता है और पीछे की ओर शाखाएं होती है :l, जिसके परिणामस्वरूप एक्सट्रीम लाइन में sedखींचने Nऔर सफल होने तक लूपिंग होता है।
e
जब अंत मैच के लिए प्रतिस्थापन सफल होता है और स्क्रिप्ट एक असफल Tएस्ट के लिए वापस शाखा नहीं करती है, तो इस तरह से आने वाले एक कमांड को एक्सक्यूट sedकरेगा :el
nl <<\\@@\nline X\nline Y\nline Z\n@@$
आप इसे देखने के लिए वहां अंतिम पंक्ति को संपादित करके अपने लिए देख सकते हैं Tl;l;e।
यह प्रिंट करता है:
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
while ... read
ऐसा करने का एक आखिरी तरीका, और शायद सबसे सरल तरीका है, while readलूप का उपयोग करना , लेकिन अच्छे कारण के लिए। शेल - (विशेष रूप से एक bashशेल) - आमतौर पर बड़ी मात्रा में या स्थिर धाराओं में इनपुट से निपटने में बहुत ही संक्षिप्त है। यह भी समझ में आता है, शेल का काम इनपुट चरित्र को चरित्र द्वारा संभालना है और अन्य कमांड को कॉल करना है जो बड़े सामान को संभाल सकता है।
लेकिन इसकी भूमिका के बारे में महत्वपूर्ण बात यह है कि शेल को read इनपुट से अधिक नहीं होना चाहिए - यह निर्दिष्ट नहीं है कि यह इनपुट या आउटपुट को बफर नहीं करता है कि यह बहुत अधिक खपत करता है या समय में पर्याप्त रिले नहीं करता है जिसे कॉल की कमी होती है - बाइट के लिए। तो readएक उत्कृष्ट इनपुट परीक्षण के लिए बनाता है - इस returnबारे में जानकारी के लिए कि क्या कोई इनपुट शेष है और आपको इसे पढ़ने के लिए अगली कमांड को कॉल करना चाहिए - लेकिन यह अन्यथा आमतौर पर जाने का सबसे अच्छा तरीका नहीं है।
हालांकि, एक उदाहरण का उपयोग कैसे किया जा सकता है read और सिंक में इनपुट को संसाधित करने के लिए अन्य आदेश कैसे हो सकते हैं :
while IFS= read -r line &&
case $line in (@@*start) :;; (*)
printf %s\\n "$line"
sed -un "/^@@.*start$/q;p";;
esac;do sed -un "/^@@.*end$/q;=;p" |
paste -d: - -
done <infile
प्रत्येक पुनरावृत्ति के लिए होने वाली पहली चीज readएक रेखा में खींचती है। यदि यह सफल होता है तो इसका अर्थ है कि लूप अभी तक ईओएफ से नहीं टकराया है और इसलिए caseयह एक स्टार्ट सीमांकक से मेल खाता है , doब्लॉक को तुरंत निष्पादित किया जाता है। एल्स, इसे printfप्रिंट करता $lineहै readऔर sedइसे कहा जाता है।
sedpहर लाइन को तब तक रिंट करेगा, जब तक कि यह स्टार्ट मार्कर से न मिल जाए - जब यह qपूरी तरह से इनपुट का उपयोग करता है। -uNbuffered स्विच जीएनयू के लिए आवश्यक है sed, क्योंकि यह नहीं बल्कि लालच से अन्यथा बफ़र सकते हैं, लेकिन - कल्पना के अनुसार - अन्य POSIX sedरों किसी विशेष विचार किए बिना काम करना चाहिए - जब तक कि <infileएक नियमित रूप से फ़ाइल है।
जब पहला sed quits, शेल doलूप के ब्लॉक को निष्पादित करता है - जो एक और कॉल करता है जो sedहर लाइन को प्रिंट करता है जब तक कि यह अंतिम मार्कर का सामना नहीं करता । यह इसके आउटपुट को पाइप करता है paste, क्योंकि यह प्रत्येक लाइन को अपनी लाइन पर प्रिंट करता है। ऐशे ही:
1
line M
2
line N
3
line O
pasteतब उन :वर्णों पर एक साथ चिपकाया जाता है , और संपूर्ण आउटपुट जैसा दिखता है:
line A
line B
1:line X
2:line Y
3:line Z
line C
line D
1:line M
2:line N
3:line O
ये केवल उदाहरण हैं - कुछ भी या तो परीक्षण में किया जा सकता है या यहां ब्लॉक कर सकते हैं, लेकिन पहली उपयोगिता को बहुत अधिक इनपुट का उपभोग नहीं करना चाहिए।
इसमें शामिल सभी उपयोगिताओं ने एक ही इनपुट पढ़ा - और अपने परिणामों को प्रिंट किया - प्रत्येक अपनी बारी में। इस तरह की चीज को लटका पाना मुश्किल हो सकता है - क्योंकि विभिन्न उपयोगिताओं में दूसरों की तुलना में अधिक बफर होगा - लेकिन आप आम तौर पर भरोसा कर सकते हैंdd , headऔर sedसही काम करने के लिए (हालांकि, जीएनयू के लिए sed, आप CLI-स्विच की जरूरत है) और आपको हमेशा भरोसा करना चाहिए read- क्योंकि यह स्वभाव से, बहुत धीमा है । और यही कारण है कि उपरोक्त लूप प्रति इनपुट ब्लॉक को केवल एक बार कॉल करता है।
nlराज्य को जमा नहीं करना है । देखो परnl -dऔर अपने चेकman/infoके बारे में जानकारी के लिए पेजnlके खंड सीमांकक ।