सभी प्रकार के कारण हैं कि एक पूरी फ़ाइल को पैटर्न स्पेस में पढ़ना गलत क्यों हो सकता है। अंतिम पंक्ति के आसपास के प्रश्न में तर्क समस्या एक आम बात है। यह sed
's रेखा चक्र से संबंधित है - जब कोई और रेखाएँ नहीं होती हैं और sed
EOF से इसका सामना होता है - यह प्रसंस्करण से बाहर निकलता है। और इसलिए यदि आप अंतिम पंक्ति में हैं और आप sed
एक और प्राप्त करने का निर्देश देते हैं तो यह वहीं रुकने वाला है और अधिक नहीं।
उस ने कहा, यदि आपको वास्तव में एक संपूर्ण फ़ाइल को पैटर्न स्पेस में पढ़ने की आवश्यकता है, तो यह संभवतः किसी अन्य उपकरण पर विचार करने योग्य है। तथ्य यह है कि sed
eponymously है धारा संपादक - या एक तार्किक डेटा ब्लॉक - - एक समय में यह एक लाइन काम करने के लिए बनाया गया है।
कई समान उपकरण हैं जो पूर्ण फ़ाइल ब्लॉक को संभालने के लिए बेहतर सुसज्जित हैं। ed
और ex
, उदाहरण के लिए, क्या sed
कर सकते हैं और क्या समान सिंटैक्स के साथ कर सकते हैं - और भी बहुत कुछ के अलावा - लेकिन यह इनपुट आउटपुट पर केवल संचालन के बजाय इसे आउटपुट में परिवर्तित करते हुए sed
, वे फ़ाइल-सिस्टम में अस्थायी बैकअप फ़ाइलों को बनाए रखते हैं । उनका काम आवश्यकतानुसार डिस्क से बफ़र किया जाता है, और वे फ़ाइल के अंत में अचानक नहीं छोड़ते हैं (और बफर स्ट्रेन के तहत बहुत कम बार निहित होते हैं) । इसके अलावा वे कई उपयोगी कार्यों की पेशकश करते हैं, जो sed
नहीं है - इस प्रकार का कि एक धारा के संदर्भ में समझ में नहीं आता है - जैसे लाइन के निशान, पूर्ववत, नामित बफ़र्स, सम्मिलित हों, और बहुत कुछ।
sed
जैसे ही यह पढ़ता है, प्राथमिक रूप से इसकी ताकत ताकत है - इसे जल्दी से, कुशलता से और स्ट्रीम में। जब आप किसी फ़ाइल को फेंकते हैं तो आप उसे दूर फेंक देते हैं और आपके द्वारा बताई गई अंतिम पंक्ति की समस्या, और बफर ओवर्रून्स, और abysmal प्रदर्शन जैसी किनारे मामले की कठिनाइयों में भाग जाते हैं - जैसा कि डेटा पार्स करता है लंबाई में एक regexp इंजन के प्रसंस्करण के समय बढ़ता है जब मैचों की गणना करता है तेजी से बढ़ता है ।
उस अंतिम बिंदु के बारे में, जिस तरह से: जब तक मैं समझता हूं कि उदाहरण का s/a/A/g
मामला बहुत ही सरल उदाहरण है और संभवतः वह वास्तविक स्क्रिप्ट नहीं है जिसके लिए आप एक इनपुट में इकट्ठा करना चाहते हैं, तो हो सकता है कि आप खुद को परिचित करने के लिए इसे अपने लायक समझ सकें। y///
। यदि आप अक्सर अपने आप को g
एक दूसरे के लिए एकल चरित्र का स्थानापन्न पाते हैं , तो y
यह आपके लिए बहुत उपयोगी हो सकता है। यह एक प्रतिस्थापन के विपरीत एक परिवर्तन है और यह बहुत जल्दी है क्योंकि यह एक रेगेक्स नहीं है। यह बाद का बिंदु भी इसे उपयोगी बना सकता है जब खाली //
पतों को संरक्षित करने और दोहराने का प्रयास किया जाता है क्योंकि यह उन्हें प्रभावित नहीं करता है लेकिन उनके द्वारा प्रभावित हो सकता है। किसी भी मामले में, y/a/A/
उसी को पूरा करने का एक अधिक सरल साधन है - और स्वैप संभव है जैसे:y/aA/Aa/
जो एक दूसरे के लिए एक पंक्ति के रूप में सभी ऊपरी / निचले हिस्से को इंटरचेंज करेगा।
आपको यह भी ध्यान देना चाहिए कि आप जिस व्यवहार का वर्णन करते हैं वह वास्तव में वैसा नहीं है जैसा कि होना चाहिए।
जीएनयू की ओर info sed
से कम से कम खरीद वाले खंड में:
N
अंतिम पंक्ति पर कमांड
sed
जब N
कोई फ़ाइल की अंतिम पंक्ति पर आदेश जारी किया जाता है , तो कुछ भी छपाई के बिना बाहर निकलने के अधिकांश संस्करण । sed
जब तक कि -n
कमांड स्विच को निर्दिष्ट नहीं किया गया है , तब तक बाहर निकलने से पहले GNU पैटर्न स्पेस प्रिंट करता है। यह चुनाव डिजाइन द्वारा है।
उदाहरण के लिए, का व्यवहार sed N foo bar
इस बात पर निर्भर करेगा कि फू की सम या विषम संख्या है। या, जब एक पैटर्न मैच के बाद अगली कुछ पंक्तियों को पढ़ने के लिए एक स्क्रिप्ट लिख रहे हैं, तो पारंपरिक कार्यान्वयन sed
आपको /foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N }
सिर्फ कुछ के बजाय कुछ लिखने के लिए मजबूर करेंगे /foo/{ N;N;N;N;N;N;N;N;N; }
।
किसी भी मामले में, सबसे सरल समाधान उन $d;N
लिपियों में उपयोग करना है जो पारंपरिक व्यवहार पर निर्भर करते हैं, या POSIXLY_CORRECT
चर को गैर-रिक्त मान पर सेट करते हैं ।
POSIXLY_CORRECT
वातावरण चर उल्लेख किया गया है क्योंकि POSIX निर्दिष्ट करता है कि अगर sed
मुठभेड़ों EOF जब प्रयास करते समय कोई N
यह उत्पादन के बिना छोड़ देना चाहिए, लेकिन जीएनयू संस्करण जानबूझकर इस मामले में मानक के साथ टूट जाता है। यह भी ध्यान दें कि व्यवहार को इस धारणा के ऊपर उचित ठहराया जाता है कि त्रुटि मामला स्ट्रीम-एडिटिंग में से एक है - स्मृति में पूरी फ़ाइल को स्लैपिंग नहीं करना।
मानक परिभाषित करता है N
के व्यवहार इस प्रकार:
N
मूल सामग्री से संलग्न सामग्री को अलग करने के लिए \n
एम्बेडेड स्पेस का उपयोग करके पैटर्न स्पेस के लिए इनपुट की अगली पंक्ति को कम करें, इसकी समाप्ति ईलाइन को लागू करें \n
। ध्यान दें कि वर्तमान लाइन संख्या बदल जाती है।
यदि इनपुट की कोई अगली पंक्ति उपलब्ध नहीं है, तो N
कमांड क्रिया स्क्रिप्ट के अंत में शाखा जाएगी और एक नया चक्र शुरू किए बिना या पैटर्न स्पेस को मानक आउटपुट पर कॉपी किए बिना छोड़ दिया जाएगा।
उस नोट पर, प्रश्न में प्रदर्शित कुछ अन्य जीएनयू-आईएमएस हैं - विशेष रूप से :
लेबल, b
रंच और {
फ़ंक्शन-संदर्भ कोष्ठक का उपयोग }
। अंगूठे के एक नियम के रूप में कोई भी sed
आदेश जो एक मनमाना पैरामीटर स्वीकार करता \n
है, उसे स्क्रिप्ट में एक ewline पर परिसीमन करने के लिए समझा जाता है । तो आज्ञा ...
:arbitrary_label_name; ...
b to_arbitrary_label_name; ...
//{ do arbitrary list of commands } ...
... उन सभी के sed
कार्यान्वयन के आधार पर गलत तरीके से प्रदर्शन की संभावना है जो उन्हें पढ़ते हैं। संभवतः उन्हें लिखा जाना चाहिए:
...;:arbitrary_label_name
...;b to_arbitrary_label_name
//{ do arbitrary list of commands
}
उसी के लिए सच है r
, w
, t
, a
, i
, और c
(और शायद कुछ और है कि मैं इस समय भूल रहा) । लगभग हर मामले में उन्हें भी लिखा जा सकता है:
sed -e :arbitrary_label_name -e b\ to_arbitary_label_name -e \
"//{ do arbitrary list of commands" -e \}
... जहां नया -e
क्लेक्शन स्टेटमेंट ईलाइन डेलिमिटर के लिए खड़ा है \n
। तो जहां जीएनयू info
पाठ एक पारंपरिक sed
कार्यान्वयन आपको यह करने के लिए मजबूर करेगा :
/foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N }
... बल्कि होना चाहिए ...
/foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N
}
... बेशक, यह सच नहीं है। इस तरह से स्क्रिप्ट लिखना थोड़ा मूर्खतापूर्ण है। ऐसा करने के बहुत अधिक सरल साधन हैं, जैसे:
printf %s\\n foo . . . . . . |
sed -ne 'H;/foo/h;x;//s/\n/&/3p;tnd
//!g;x;$!d;:nd' -e 'l;$a\' \
-e 'this is the last line'
... जो प्रिंट:
foo
.
.
.
foo\n.\n.\n.$
.$
this is the last line
... क्योंकि t
अधिकांश कमांड - जैसे अधिकांश sed
कमांड - अपने रिटर्न रजिस्टर को रीफ्रेश करने के लिए लाइन साइकल पर निर्भर करता है और यहां लाइन साइकल को अधिकतर काम करने की अनुमति है। जब आप किसी फ़ाइल को खिसकाते हैं, तो यह एक और ट्रेडऑफ़ है - लाइन चक्र कभी भी ताज़ा नहीं होता है, और इसलिए कई परीक्षण असामान्य रूप से व्यवहार करेंगे।
उपरोक्त आदेश अधिक-पहुंच वाले इनपुट का जोखिम नहीं उठाता है क्योंकि यह जो कुछ पढ़ता है उसे सत्यापित करने के लिए बस कुछ सरल परीक्षण करता है। साथ H
पुराने सभी लाइनों पकड़ अंतरिक्ष के साथ जोड़ दिया जाता है, लेकिन अगर एक पंक्ति से मेल खाती /foo/
यह अधिलेखित कर देता है h
पुराने अंतरिक्ष। बफ़र्स को अगले ई x
बदल दिया जाता है, और एक सशर्त s///
ubstration का प्रयास किया जाता है यदि बफर की सामग्री को //
संबोधित किया गया अंतिम पैटर्न। दूसरे शब्दों //s/\n/&/3p
में, अपने साथ होल्ड स्पेस में तीसरी न्यूलाइन को बदलने का प्रयास करता है और यदि वर्तमान में मैच हो रहा है तो स्पेस को प्रिंट कर सकता है /foo/
। अगर वह ओ.टी. ईटेल लेबल के t
लिए स्क्रिप्ट शाखाओं को सफल करता है - जो एक ook करता है और स्क्रिप्ट को लपेटता है।n
d
l
इस मामले में कि दोनों /foo/
और एक तीसरी न्यूलाइन को होल्ड स्पेस में एक साथ मिलान नहीं किया जा सकता है, फिर //!g
बफ़र /foo/
को मेल नहीं होने पर बफर को अधिलेखित कर देगा , या, यदि यह मिलान किया जाता है, तो यह बफ़र को अधिलेखित कर देगा यदि एक \n
ईव्लीन मेल नहीं खाता है (/foo/
ताकि साथ बदल रहा है खुद) । यह थोड़ा सूक्ष्म परीक्षण बफर को बिना किसी खिंचाव के लंबे समय तक भरने से रोकता है /foo/
और यह सुनिश्चित करता है कि इनपुट पर ढेर न होने के कारण प्रक्रिया तेज़ हो। नो /foo/
या //s/\n/&/3p
फेल केस में फॉलो करने पर बफ़र्स को फिर से स्वैप किया जाता है और हर लाइन को डिलीट कर दिया जाता है।
वह अंतिम - अंतिम पंक्ति $!d
- एक सरल प्रदर्शन है कि कैसे एक शीर्ष-डाउन sed
स्क्रिप्ट को आसानी से कई मामलों को संभालने के लिए बनाया जा सकता है। जब आपकी सामान्य विधि सबसे सामान्य के साथ शुरू होने वाले अवांछित मामलों को दूर करने के लिए है और सबसे विशिष्ट की ओर काम कर रही है, तो किनारे के मामलों को और अधिक आसानी से नियंत्रित किया जा सकता है, क्योंकि उन्हें आपके अन्य वांछित डेटा के साथ स्क्रिप्ट के अंत तक गिरने की अनुमति है यह सब आप चाहते हैं केवल डेटा के साथ छोड़ दिया जाता है लपेटता है। एक बंद लूप से ऐसे किनारे के मामलों को लाने के लिए हालांकि यह करना अधिक कठिन हो सकता है।
और इसलिए यहां मुझे आखिरी बात कहनी है: यदि आपको वास्तव में एक पूरी फ़ाइल में खींचना है, तो आप इसे करने के लिए लाइन चक्र पर भरोसा करके थोड़ा कम काम करने के लिए खड़े हो सकते हैं। आमतौर पर आप लुकहेड के लिए एक्सटN
और n
एक्सट का उपयोग करते हैं - क्योंकि वे लाइन चक्र के आगे बढ़ते हैं। एक लूप के भीतर बंद लूप को अनावश्यक रूप से लागू करने के बजाय - जैसे कि लाइन चक्र वैसे भी एक साधारण पढ़ा हुआ लूप है - यदि आपका उद्देश्य केवल इनपुट को अंधाधुंध रूप से इकट्ठा करना है, तो संभवतः ऐसा करना आसान है:sed
sed 'H;1h;$!d;x;...'
... जो पूरी फ़ाइल को इकट्ठा करेगा या कोशिश करना बंद कर देगा।
एक साइड नोट के बारे में N
और अंतिम पंक्ति व्यवहार ...
जब मेरे पास परीक्षण करने के लिए मेरे पास उपलब्ध उपकरण नहीं हैं, तो विचार करें कि N
जब रीडिंग और इन-प्लेस संपादन अलग तरीके से व्यवहार करता है अगर संपादित की गई फ़ाइल अगले रीड्रिथ के लिए स्क्रिप्ट फ़ाइल है।