Sed में 'होल्ड स्पेस ’और space पैटर्न स्पेस’ का कॉन्सेप्ट


86

मैं sed में दो अवधारणाओं से भ्रमित हूं: स्पेस और पैटर्न स्पेस पकड़ो। क्या कोई उन्हें समझाने में मदद कर सकता है?

यहाँ मैनुअल का एक टुकड़ा है:

h H    Copy/append pattern space to hold space.
g G    Copy/append hold space to pattern space.

n N    Read/append the next line of input into the pattern space.

ये छह आज्ञाएँ वास्तव में मुझे भ्रमित करती हैं।


4
इसे स्वयं आज़माएँ:echo $'1\n2\n3\n4' | sed -n '1~2h;2~2{p;x;p}'
कोरोबा

4
भ्रमित न हों, बस उनका उपयोग न करें। एक लाइन पर सरल प्रतिस्थापन के अलावा किसी भी चीज़ के लिए आपको awk का उपयोग करना चाहिए, न कि sed। स्पेस, पैटर्न स्पेस और 95% सेड लैंग्वेज कंस्ट्रक्शन का आविष्कार जाग से पहले किया गया था जब कोई बेहतर विकल्प नहीं था। 1970 के दशक के मध्य में awk का आविष्कार होते ही वे अप्रचलित हो गए और आज भी केवल जीवित लोगों को ही रखा जाता है, जो awk में केवल और निडरता से करने के बजाय seds arcane सिंटैक्स का उपयोग करके समस्याओं को हल करने का आनंद लेते हैं। यदि आप sed में s, g, और p (with -n) से अधिक उपयोग कर रहे हैं तो आप निश्चित रूप से गलत टूल का उपयोग कर रहे हैं।
एड मॉर्टन

26
मॉर्टन awk संरचित डेटा के साथ काम करता है (प्रत्येक पंक्ति में समान संरचना है)। सेड कच्चे यादृच्छिक डेटा के साथ काम करने के लिए है। तो आप बस sed के बजाय awk का उपयोग नहीं कर सकते।
पिथिकोस

5
मैं दृढ़ता से पढ़ने की सलाह देता हूं info sed। यह नंगे आदमी पृष्ठ की तुलना में बहुत अधिक विस्तृत है।
फर्नांडो बैसो

4
मैं पिथिकोस से सहमत हूं। मैं मोर्टन के रूप में लेन नीचे चला गया, और खुद से वही सवाल पूछा जो मॉर्टन ने किया था। हालाँकि, मैं अभी तक सेड को आसानी से खारिज नहीं कर सका।
आइजेनफील्ड

जवाबों:


111

जब sed एक फ़ाइल लाइन को लाइन से पढ़ता है, तो वर्तमान में पढ़ी गई लाइन को पैटर्न बफर (पैटर्न स्पेस) में डाला जाता है । पैटर्न बफर अस्थायी बफर की तरह है, जहां वर्तमान जानकारी संग्रहीत की जाती है। जब आप प्रिंट करने के लिए sed बताते हैं, तो यह पैटर्न बफर प्रिंट करता है।

बफ़र / होल्ड स्पेस एक लॉन्ग-टर्म स्टोरेज की तरह है, जैसे कि आप किसी चीज़ को पकड़ सकते हैं, उसे स्टोर कर सकते हैं और बाद में इसका दोबारा इस्तेमाल कर सकते हैं जब सेड अपनी लाइन को प्रोसेस कर रहा है। आप सीधे होल्ड स्पेस को संसाधित नहीं करते हैं, इसके बजाय, आपको इसे कॉपी करने की आवश्यकता है या यदि आप इसके साथ कुछ करना चाहते हैं तो पैटर्न स्पेस को जोड़ना होगा। उदाहरण के लिए, प्रिंट कमांड pकेवल पैटर्न स्पेस प्रिंट करता है। इसी तरह, sपैटर्न अंतरिक्ष पर चल रही है।

यहाँ एक उदाहरण है:

sed -n '1!G;h;$p'

(-n विकल्प लाइनों की स्वचालित छपाई को दबा देता है)

वहाँ तीन आदेशों यहां हैं: 1!G, hऔर $p1!Gएक पता है, 1(पहली पंक्ति), लेकिन !इसका मतलब है कि कमांड को हर जगह निष्पादित किया जाएगा लेकिन पहली पंक्ति पर। $pदूसरी ओर केवल अंतिम पंक्ति पर ही अमल किया जाएगा। तो क्या होता है:

  1. पहली पंक्ति को पढ़ने और स्वचालित रूप से पैटर्न स्पेस में डाला जाता है
  2. पहली पंक्ति में, पहली कमांड निष्पादित नहीं की जाती है; hपहली पंक्ति को होल्ड स्पेस में कॉपी करता है।
  3. अब दूसरी पंक्ति पैटर्न स्पेस में जो कुछ भी थी उसे बदल देती है
  4. दूसरी पंक्ति में, पहले हम निष्पादित Gकरते हैं, पैटर्न बफर को होल्ड बफर की सामग्री को जोड़ते हुए, इसे एक नई रेखा द्वारा अलग करते हैं। पैटर्न स्पेस में अब दूसरी पंक्ति, एक नई रेखा और पहली पंक्ति शामिल है।
  5. फिर, hकमांड पैटर्न बफर के समाप्‍त सामग्री को होल्ड स्पेस में सम्मिलित करता है, जो अब उलट लाइनों को दो और एक रखता है।
  6. हम पंक्ति संख्या तीन पर जाते हैं - ऊपर बिंदु (3) पर जाएं।

अंत में, अंतिम पंक्ति पढ़ने के बाद और होल्ड स्पेस (रिवर्स ऑर्डर में सभी पिछली लाइनों वाले) को पैटर्न स्पेस में जोड़ा गया है, पैटर्न स्पेस के साथ प्रिंट किया गया है p। जैसा कि आपने अनुमान लगाया है, ऊपर ठीक वही करता है जो tacकमांड करता है - फाइल को रिवर्स में प्रिंट करता है।


3
क्या G और h विकल्प "कट और अपेंड" की तरह काम करता है ?? यह "कॉपी और अपेंड" ऑपरेशन की तरह नहीं दिखता है।
मुस्कान

नेस्टेड कमांड (घुंघराले ब्रेस) का उपयोग करते समय पैटर्न और होल्ड स्पेस के साथ क्या होता है? '195,210{/add/p}'… क्या पैटर्न में शामिल लाइन के समूह की अंतिम पंक्ति को निकालना संभव है?
सैंडबर्ग

17

@ ईडी मॉर्टन: मैं यहां आपसे असहमत हूं। मुझे sedबहुत उपयोगी और सरल मिला (एक बार जब आप पैटर्न की अवधारणा को टटोलते हैं और बफ़र्स को पकड़ते हैं) तो बहुस्तरीय हरियाणवी करने के लिए एक सुरुचिपूर्ण तरीके के साथ आते हैं।

उदाहरण के लिए, चलिए एक टेक्स्ट फाइल लेते हैं जिसमें होस्टनाम और प्रत्येक होस्ट के बारे में कुछ जानकारी होती है, जिसके बीच में बहुत सारे कबाड़ होते हैं जिनकी मुझे परवाह नहीं है।

Host: foo1
some junk, doesnt matter
some junk, doesnt matter
Info: about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Info: a second line about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Host: foo2
some junk, doesnt matter
Info: about foo2 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter

मेरे लिए, होस्टनाम के साथ लाइनों को प्राप्त करने के लिए एक awk स्क्रिप्ट और संबंधित infoलाइन मुझे sed के साथ जो करने में सक्षम है, उससे थोड़ा अधिक लगेगा:

sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt

आउटपुट जैसा दिखता है:

Host: foo1
Info: about foo1 that I really care about!!
Host: foo1
Info: a second line about foo1 that I really care about!!
Host: foo2
Info: about foo2 that I really care about!!

(ध्यान दें कि Host: foo1आउटपुट में दो बार दिखाई देता है।)

स्पष्टीकरण:

  1. -n स्पष्ट रूप से मुद्रित होने तक आउटपुट अक्षम करता है
  2. पहला मैच, Host:लाइन को होल्ड बफ़र (h) में पाता और डालता है
  3. दूसरा मैच, अगली जानकारी पाता है: लाइन, लेकिन पहले बफर (x) पैटर्न बफर में वर्तमान लाइन होल्ड बफर के साथ, और प्रिंट (पी) Host:लाइन, फिर फिर से एक्सचेंज (एक्स) और प्रिंट (पी) इन्फो: लाइन।

हां, यह एक सरलीकृत उदाहरण है, लेकिन मुझे संदेह है कि यह एक सामान्य मुद्दा है जिसे एक साधारण सेड वन-लाइनर द्वारा जल्दी से निपटा दिया गया था। बहुत अधिक जटिल कार्यों के लिए, जैसे कि आप किसी दिए गए, अनुमानित अनुक्रम पर भरोसा नहीं कर सकते हैं, जाग बेहतर अनुकूल हो सकता है।


2
इस मामले में हालांकि आप सिर्फ grep का उपयोग कर सकते हैं:grep 'Host\|Info'
Pithikos

यदि किसी Host के बाद दो Info लाइनें हैं, तो @JensJenson चाहता है कि दोनों इन्फो लाइनें एक इंफो लाइन से पहले हो। मुझे लगता है कि मैं तदनुसार उत्तर संपादित करूंगा। पिथिकोस, ग्रीप तब पर्याप्त नहीं होगा।
हारून मैकडैड

3
@JensJenson, awkआपके सेड कोड के बराबर भी बहुत छोटा है:awk '/Host:/{hold=$0}; /Info/{print hold; print;}' myfile.txt
हारून मैकडैड

11

हालांकि @ जनवरी का जवाब और उदाहरण अच्छा है, स्पष्टीकरण मेरे लिए पर्याप्त नहीं था। मुझे बहुत कुछ खोजना और सीखना था जब तक कि मैं यह समझने में कामयाब नहीं हो गया कि वास्तव में यह कैसे sed -n '1!G;h;$p'काम करता है। इसलिए मैं अपने जैसे किसी के लिए आदेश पर विस्तार से बताना चाहूंगा।

सबसे पहले, आइए देखें कि कमांड क्या करता है।

$ echo {a..d} | tr ' ' '\n' # Prints from 'a' to 'd' in each line
a
b
c
d
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;$p'
d
c
b
a

यह जैसे इनपुट को उलट देता है tac कमांड करता है।

sedलाइन-बाय-लाइन पढ़ता है, तो देखते हैं कि प्रत्येक लाइन पर पैटन स्पेस और होल्ड स्पेस पर क्या होता है । जैसा कि hकमांड पैटर्न स्पेस की सामग्री को होल्ड स्पेस पर कॉपी करता है, दोनों स्पेस में एक ही टेक्स्ट होता है।

Read line    Pattern Space / Hold Space    Command executed
-----------------------------------------------------------
a            a$                            h
b            b\na$                         1!G;h
c            c\nb\na$                      1!G;h
d            d\nc\nb\na$                   1!G;h;$p

अंतिम पंक्ति में, $pप्रिंट d\nc\nb\na$किए गए प्रिंट

d
c
b
a

यदि आप प्रत्येक पंक्ति के लिए पैटर्न स्थान देखना चाहते हैं, तो आप एक lकमांड जोड़ सकते हैं ।

$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;l;$p'
a$
b\na$
c\nb\na$
d\nc\nb\na$
d
c
b
a

मुझे यह वीडियो ट्यूटोरियल देखने में बहुत मददगार लगा। यह समझना कि sed कैसे काम करता है , जैसा कि आदमी दिखाता है कि प्रत्येक स्थान का उपयोग चरण दर चरण कैसे किया जाएगा। पकड़े गए स्थान को 4 के ट्यूटोरियल में संदर्भित किया गया है, लेकिन मैं सभी वीडियो देखने की सलाह देता हूं यदि आप परिचित नहीं हैं sed

इसके अलावा GNU sed दस्तावेज़ और ब्रूस बार्नेट के एसआईडी ट्यूटोरियल बहुत अच्छे संदर्भ हैं।


2
मुझे लगता है कि यह उल्लेख करना भी उपयोगी होगा कि सभी व्यावहारिक उद्देश्यों के लिए स्थान खाली है जब तक कि हम इसमें कुछ न जोड़ दें।
नवीद
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.