मैं तुम्हारे साथ सहमत होगा - यह शायद है एक सामान्य समस्या है। कुछ सामान्य उपयोगिताओं में इसे संभालने के लिए कुछ सुविधाएं हैं, हालांकि।
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
। जब ऐसा होता है, तो यह इनपुट के साथ e
xecutes का nl
प्रतिनिधित्व करता है, <<
यहां इसके बाकी सभी पैटर्न-स्पेस के लिए दस्तावेज़ के रूप में दर्शाया गया है।
वर्कफ़्लो इस तरह है:
/^@@.*start$/!b
- अगर एक
^
पूरी पंक्ति $
है !
नहीं /
से मेल /
ऊपर पैटर्न, तो यह है b
स्क्रिप्ट से बाहर ranched और autoprinted - तो इस बिंदु से पर हम केवल जो पैटर्न के साथ शुरू हुआ लाइनों की एक श्रृंखला के साथ काम कर रहे हैं।
s//nl <<\\@@/
- खाली
s//
फ़ील्ड मिलान के /
लिए अंतिम पते के लिए खड़ा है sed
- इसलिए यह कमांड इसके बजाय पूरी @@.*start
लाइन को प्रतिस्थापित करता है nl <<\\@@
।
:l;N
:
आदेश एक शाखा लेबल को परिभाषित करता है - यहाँ मैं एक का नाम सेट :l
हाबिल। N
Ext आदेश अगले एक के बाद पैटर्न अंतरिक्ष के लिए इनपुट की रेखा भी संलग्न \n
ewline चरित्र। यह \n
एक sed
पैटर्न स्पेस में ewline प्राप्त करने के लिए केवल कुछ तरीकों में से एक है - \n
ewline वर्ण एक व्युत्पन्न के लिए एक निश्चित सीमांकक है sed
जो इसे थोड़ी देर कर रहा है।
s/\(\n@@\)[^\n]*end$/\1/
s///
एक शुरुआत के बाद और केवल एक अंतिम पंक्ति की पहली घटना के बाद ही यह ubstration सफल हो सकता है । यह केवल एक पैटर्न स्पेस पर कार्य करेगा जिसमें पैटर्न स्पेस के बहुत अंत को चिह्नित करते हुए \n
तुरंत अंतिम ईवलाइन का पालन किया जाता है। जब यह कार्य करता है, तो यह पूरे मिलान वाले स्ट्रिंग को पहले समूह के साथ बदल देता है , या ।@@.*end
$
\1
\(
\)
\n@@
Tl
T
किसी लेबल की स्था आदेश शाखाओं (यदि उपलब्ध) अगर एक सफल प्रतिस्थापन पिछली बार एक इनपुट लाइन पैटर्न अंतरिक्ष में खींचा गया था के बाद से नहीं हुआ (मैं w / कर के रूप में N
) । इसका मतलब यह है कि हर बार एक \n
ईवालाइन को पैटर्न स्पेस से जोड़ा जाता है जो आपके अंतिम सीमांकक से मेल नहीं खाता है, एस्ट्रल T
कमांड विफल रहता है और पीछे की ओर शाखाएं होती है :l
, जिसके परिणामस्वरूप एक्सट्रीम लाइन में sed
खींचने N
और सफल होने तक लूपिंग होता है।
e
जब अंत मैच के लिए प्रतिस्थापन सफल होता है और स्क्रिप्ट एक असफल T
एस्ट के लिए वापस शाखा नहीं करती है, तो इस तरह से आने वाले एक कमांड को एक्सक्यूट sed
करेगा :e
l
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
इसे कहा जाता है।
sed
p
हर लाइन को तब तक रिंट करेगा, जब तक कि यह स्टार्ट मार्कर से न मिल जाए - जब यह q
पूरी तरह से इनपुट का उपयोग करता है। -u
Nbuffered स्विच जीएनयू के लिए आवश्यक है sed
, क्योंकि यह नहीं बल्कि लालच से अन्यथा बफ़र सकते हैं, लेकिन - कल्पना के अनुसार - अन्य POSIX sed
रों किसी विशेष विचार किए बिना काम करना चाहिए - जब तक कि <infile
एक नियमित रूप से फ़ाइल है।
जब पहला sed
q
uits, शेल 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
के खंड सीमांकक ।