2009-04-27 16 views
5

मैं खोल प्रोग्रामिंग में पूरी तरह खो गया हूं, मुख्य रूप से क्योंकि प्रत्येक साइट का उपयोग मैं पैटर्न मिलान करने के लिए अलग-अलग टूल प्रदान करता हूं। तो मेरा सवाल यह है कि पाइप स्ट्रीम में सरल पैटर्न मिलान करने के लिए किस उपकरण का उपयोग करना है।कोट्स में मिलान करने वाला टेक्स्ट (नौसिखिया)

संदर्भ: मेरे पास name.conf फ़ाइल है, और मुझे आगे की प्रक्रिया के लिए एक साधारण फ़ाइल में सभी जोन नामों की आवश्यकता है। तो मैं ~ $ बिल्ली नामित करता हूं। लोकल | grep जोन और पूरी तरह से यहाँ खो दिया। मेरा आउटपुट फॉर्म 'जोन' डोमेन.tld "{'में ~ सौ या तो न्यूलाइन है और मुझे डबल कोट्स में टेक्स्ट चाहिए।

ऐसा करने का तरीका दिखाने के लिए धन्यवाद।

जम्मू

उत्तर

23

मैं तुम्हारे लिए क्या देख रहे हैं लगता है sed है ... यह एक रों tream एड itor जो आपको एक पंक्ति-दर-पंक्ति आधार पर प्रतिस्थापन करते हैं जाएगा।

जैसा कि आप इसे समझा रहे हैं, आदेश 'cat name.local | ग्रेप क्षेत्र 'आप एक निर्गम एक छोटे से इस तरह देता है:

zone "domain1.tld" { 
zone "domain2.tld" { 
zone "domain3.tld" { 
zone "domain4.tld" { 

मैं तुम्हें उत्पादन कुछ इस तरह होना चाहते हैं अनुमान लगा रहा हूँ, जब से तुम आप दोहरे उद्धरण चिह्नों में पाठ की जरूरत है ने कहा:

"domain1.tld" 
"domain2.tld" 
"domain3.tld" 
"domain4.tld" 

तो, हकीकत में, प्रत्येक पंक्ति से हम केवल डबल-कोट्स (डबल-कोट्स सहित) के बीच टेक्स्ट चाहते हैं।

मुझे यकीन नहीं है कि आप Regular Expressions से परिचित हैं, लेकिन वे एक अमूल्य टूल हैं किसी भी व्यक्ति के लिए खोल स्क्रिप्ट लिखना। उदाहरण के लिए, नियमित अभिव्यक्ति /.o.e/ किसी भी पंक्ति से मेल खाती है जहां दूसरे अक्षर वाला शब्द कम-मामला o था, और चौथा e था। इस तरह "zone" स्ट्रिंग वाली शब्द से मेल खाएंगे, "tone", या "I am tone-deaf."

चाल वहाँ . (डॉट) चरित्र का इस्तेमाल किया गया "किसी भी पत्र" मतलब करने के लिए। * जैसे कुछ अन्य विशेष पात्र हैं जिसका अर्थ है "पिछले वर्ण 0 या अधिक बार दोहराएं"। इस प्रकार a* की तरह एक नियमित अभिव्यक्ति "a" से मेल खाएंगे, "aaaaaaa", या एक खाली स्ट्रिंग: ""

तो आप उपयोग कर, कोट के अंदर स्ट्रिंग से मेल कर सकते हैं: /".*"/

एक और बात आप के बारे में पता होगा नहीं है sed (और टिप्पणियों के द्वारा, आप पहले से ही करते हैं!) - यह बैकट्रैकिंग की अनुमति देता है। एक बार जब आप इसे एक शब्द को पहचानने के बारे में बताएंगे, तो आप प्रतिस्थापन के हिस्से के रूप में उस शब्द का उपयोग कर सकते हैं। इस सूची में

Billy "The Kid" Smith 
Jimmy "The Fish" Stuart 
Chuck "The Man" Norris 

: उदाहरण के लिए, मान लें कि आप इस सूची बारी करना चाहता था जाने

The Kid 
The Fish 
The Man 

सबसे पहले, आप कोट के अंदर स्ट्रिंग के लिए देखो चाहते हैं। हमने पहले ही देखा है, यह /".*"/ था।

अगला, हम उद्धरण के अंदर क्या उपयोग करना चाहते हैं।हम समूह यह कोष्ठक का उपयोग कर सकते हैं: /"(.*)"/

अगर हम एक अंडरस्कोर से उद्धरण के साथ पाठ को बदलने के लिए चाहते थे, हम एक की जगह करना चाहते हैं: s/"(.*)"/_/, और कहा कि हमारे साथ छोड़ना होगा:

Billy _ Smith 
Jimmy _ Stuart 
Chuck _ Norris 

लेकिन हमारे पास बैकट्रैकिंग है! यह हमें \1 प्रतीक का उपयोग करके, माता-पिता के अंदर क्या था याद करेगा। तो अगर अब हम करते हैं: s/"(.*)"/\1/ हम मिल जाएगा:

Billy The Kid Smith 
Jimmy The Fish Stuart 
Chuck The Man Norris 

क्योंकि उद्धरण नहीं थे कोष्ठक में, वे \1 की सामग्री का हिस्सा नहीं थे!

केवल डबल-कोट्स के अंदर सामान छोड़ने के लिए, हमें पूरी लाइन से मिलान करने की आवश्यकता है। (। जिसका अर्थ है "पंक्ति के अंत") है कि हम ^ ("पंक्ति के आरंभ" जिसका अर्थ है), और $ है

तो अब अगर हम s/^.*"(.*)".*$/\1/ का उपयोग करने के लिए, हम मिल जाएगा:

The Kid 
The Fish 
The Man 

क्यों? के बाएं-से-दाएं नियमित अभिव्यक्ति s/^.*"(.*)".*$/\1/ पढ़ने दें:

  • s/ - लाइन की शुरुआत के लिए देखो - एक प्रतिस्थापन नियमित अभिव्यक्ति
  • ^ शुरू करो। वहां से शुरू करो।
  • .* -, जा रहा हर चरित्र को पढ़ने, जब तक ...
  • " रखें - ... जब तक आप एक डबल उद्धरण तक पहुँचते हैं।
  • ( - एक समूह को एक अक्षर शुरू करें जिसे हम बैकट्रैकिंग के बाद बाद में याद करना चाहेंगे।
  • .* - जा रहा रखें, हर चरित्र को पढ़ने, जब तक ...
  • ) - (! समूह PSSST बंद)
  • " - ... जब तक आप तक पहुँचने के एक दोहरे-उद्धरण।
  • .* -, जा रहा हर चरित्र को पढ़ने, जब तक रहो ...
  • $ - पंक्ति के अंत!

  • / - का उपयोग क्या बदलने के लिए क्या आप

  • \1 मिलान किया इस के बाद है - पहले समूह (क्या कोष्ठक में था) का मिलान नहीं हुआ की सामग्री को पेस्ट करें।
  • / - नियमित अभिव्यक्ति

सादे अंग्रेजी में के अंत:। "पूरी पंक्ति पढ़ें, एक तरफ डबल उद्धरण के बीच पाठ को कॉपी फिर डबल qoutes के बीच सामग्री के साथ पूरी पंक्ति की जगह।"

तुम भी पाठ s/^.*"(.*)".*$/"\1"/ की जगह के आसपास दोहरे-उद्धरण जोड़ सकते हैं, तो हम मिल जाएगा:

"The Kid" 
"The Fish" 
"The Man" 

और वह sed द्वारा इस्तेमाल किया जा सकता उद्धरण के भीतर से सामग्री के साथ लाइन को बदलने के लिए:

sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/" 

(यह सिर्फ खोल-भाग निकले डबल उद्धरण और स्लैश और सामान से निपटने के लिए है।)

तो पूरे आदेश wo की तरह कुछ हो uld:

cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/" 
+0

हाँ, मैं अभी इसका उपयोग कर रहा हूं, लेकिन मुझे लगता है कि ऐसा करने का आसान तरीका होना चाहिए, क्योंकि अब मैं sed -e/zone "// g '| sed -e's /" { // जी 'बस मध्य से मेल खाने की बजाय फ़ाइल की शुरुआत और अंत को हटाने के लिए। – jpou

+1

शुरुआत और अंत से शेविंग पूरी तरह से स्वीकार्य है। यह कोई प्रतियोगिता नहीं है - अगर यह काम करता है, तो यह ठीक है। यदि आप उद्धरणों में पाठ से मिलान करके ऐसा करना चाहते हैं, तो 'कैप्चरिंग समूह' पर एक नज़र डालें। – zoul

+0

उह। मैंने इसे बहुत लंबा टाइपिंग बिताया, और यह अभी भी नहीं हुआ है ... ऐसा लगता है कि हर कोई मुझे इसे मार देता है। लेकिन मुझे खुशी है कि आप इसे पहले से ही समझ चुके हैं :-) – scraimer

1

1.

[email protected]:etc$ cat named.conf | grep zone 
zone "." IN { 
zone "localhost" IN { 
    file "localhost.zone"; 
zone "0.0.127.in-addr.arpa" IN { 

2.

[email protected]:etc$ cat named.conf | grep ^zone 
zone "." IN { 
zone "localhost" IN { 
zone "0.0.127.in-addr.arpa" IN { 

3.

[email protected]:etc$ cat named.conf | grep ^zone | sed 's/.*"\([^"]*\)".*/\1/' 
. 
localhost 
0.0.127.in-addr.arpa 

regexp .*"\([^"]*\)".* है, जो मेल खाता है:

  1. किसी भी वर्णों की संख्या: .*
    • एक उद्धरण: "
    • शुरू होता है बाद में याद रखने के लिए: \(
    • बोली को छोड़कर किसी भी वर्ण: [^"]*
    • समूह समाप्त हो जाती है याद करने के लिए: \)
    • बंद करने वाला उद्धरण : "
    • और वर्णों की संख्या: .*

जब sed बुला, वाक्य रचना 's/what_to_match/what_to_replace_it_with/' है। आपके regexp को bash द्वारा विस्तारित होने से रोकने के लिए एकल उद्धरण हैं। जब आप माता-पिता का उपयोग करते हुए regexp में कुछ "याद रखें", तो आप इसे \1, \2 आदि के रूप में याद कर सकते हैं। थोड़ी देर के लिए इसके साथ फ़िल्ड करें।

2

ठीक है, कोई भी अभी तक उल्लेख किया cut, इसलिए, साबित करने के लिए वहाँ खोल के साथ कुछ करने के लिए कई तरीके हैं कि:

% grep '^zone' /etc/bind/named.conf | cut -d' ' -f2 
"gennic.net" 
"generic-nic.net" 
"dyn.generic-nic.net" 
"langtag.net" 
0

जब तक किसी को बाहर इशारा कर रही है sed/awk, मैं जा रहा हूँ इंगित करें कि grep अनावश्यक है।

sed -ne '/^zone/{s/.*"\([^"]*\)".*/\1/;p}' /etc/bind/named.conf 

यह आपको उद्धरण के बिना जो खोज रहा है उसे देता है (उन्हें रखने के लिए कोष्ठक के अंदर उद्धरण स्थानांतरित करें)।awk में, यह उद्धरण के साथ और भी आसान है:

awk '/^zone/{print $2}' /etc/bind/named.conf 

मैं के रूप में संभव है (न कि अधिक) के रूप में ज्यादा पाइपलाइनों से बचने की कोशिश। याद रखें, Don't pipe cat। इसकी आवश्यकता नहीं है। और, grep के काम को डुप्लिकेट करने के रूप में अजीब और sed के रूप में, पाइप grep, या तो नहीं है। कम से कम, sed या awk में नहीं।

व्यक्तिगत रूप से, शायद मैंने पेर्ल का उपयोग किया होगा। लेकिन ऐसा इसलिए है क्योंकि मैंने शायद जो कुछ भी आप कर रहे हैं, वह सब कुछ किया होगा, जो इसे एक मामूली विस्तार दे रहा है (और पूरी फाइल को एक साथ करने और फिर से सब कुछ के खिलाफ regex करने में सक्षम होने के कारण, \ n के मामलों के लिए एक बोनस होगा मैं/etc/bind नियंत्रित नहीं करता, जैसे कि साझा वेबहोस्ट पर)। लेकिन, अगर मैं इसे खोल में करना चाहता था, तो उपर्युक्त दो में से एक तरीका होगा जिस तरह से मैं उससे संपर्क करूंगा।

संबंधित मुद्दे