गैर-मिलान लाइनों को sed अनदेखा करें


93

मैं sedकुछ अभिव्यक्ति के अनुसार फ़िल्टर मिलान लाइनें कैसे बना सकता हूं , लेकिन गैर-मिलान लाइनों को अनदेखा करें, बजाय उन्हें प्रिंट करने के?

एक वास्तविक उदाहरण के रूप में, मैं scalacफाइलों के एक सेट पर (स्काला कंपाइलर) चलाना चाहता हूं , और इसके -verboseआउटपुट से .classबनाई गई फाइलें पढ़ता हूं । scalac -verboseसंदेशों का एक गुच्छा आउटपुट करता है, लेकिन हम केवल फॉर्म के इच्छुक हैं [wrote some-class-name.class]। वर्तमान में मैं यह कर रहा हूं ( |&अगले कार्यक्रम के लिए स्टडर को पाइप करने का 4.0 तरीका है):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'

यह उन संदेशों से फ़ाइल नामों को निकालेगा जिसमें हम रुचि रखते हैं, लेकिन अन्य सभी संदेशों को अपरिवर्तित से गुजरने देंगे! बेशक हम इसके बजाय कर सकते हैं:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
  sed 's/^\[wrote \(.*\.class\)\]$/\1/'

जो काम करता है लेकिन वास्तविक समस्या के आसपास जाने में बहुत पसंद करता है, जो sedकि इनपुट से गैर-मिलान लाइनों को अनदेखा करने का निर्देश है। तो हम इसे कैसे करते हैं?


2
स्वीकृत उत्तर mouviciel द्वारा एक होना चाहिए: stackoverflow.com/a/1665574/869951
ओलिवर

जवाबों:


90

सादे तलछट के साथ एक और तरीका:

sed -e 's/.../.../;t;d'

s///एक सबस्टेशन है, tबिना किसी लेबल के सशर्त रूप से सभी निम्न आदेशों को छोड़ देता है, dलाइन को हटा देता है।

Perl या grep की कोई आवश्यकता नहीं है।

(निकोलस रिले के सुझाव के बाद संपादित)


3
OS X 10.8.2 पर मुझे एक अर्धविराम के बजाय एक नई रेखा के साथ अलग होना पड़ा txऔर dजैसा कि मुझे मिल रहा था undefined label 'x;d;:x'
davidchambers

6
इससे भी बेहतर: sed -e 's/.../.../' -e 'tx' -e 'd' -e ':x'(एक समान प्रश्न पर एक टिप्पणी में सुझाव दिया गया है )।
davidchambers

1
यदि लेबल की आपूर्ति नहीं होती है, तो 't' स्क्रिप्ट के अंत में स्थानांतरित हो जाएगा, इसलिए सरल sed -e 's/.../.../' -e 't' -e 'd':।
निकोलस रिले

लोग न -eतो विकल्प का अर्थ जानते हैं और न ही इसके बारे में आमतौर पर उल्लेख करते हैं।
फ्रेड्रिक गॉस ने

246

यदि आप उन लाइनों को प्रिंट नहीं करना चाहते हैं जो मेल नहीं खाती हैं, तो आप के संयोजन का उपयोग कर सकते हैं

  • -n विकल्प जो sed को प्रिंट न करने के लिए कहता है
  • p फ्लैग जो मैचेड को प्रिंट करने के लिए sed को बताता है

यह देता है:

sed -n 's/.../.../p'

3
इस दृष्टिकोण के लिए एक नकारात्मक पक्ष यह है कि यदि आपके पास कई अभिव्यक्ति हैं जो मेल खाते हैं, तो परिणाम भी कई बार मुद्रित किया जाएगा। उदाहरण के लिए: echo foo | sed -n -e 's/foo/bar/p' -e 's/bar/oof/p'दोनों आउटपुट barऔर oofअलग-अलग लाइनों पर। हालांकि गोटो-लेबल विविधता कई पैटर्न को संभाल नहीं सकती है क्योंकि यह पहला पैटर्न मेल नहीं खाता है तो यह लाइन को हटा देगा।
रोज़ी

@Rapsey ऐसा इसलिए है क्योंकि आप इसे दो बार प्रिंट करने के लिए कह रहे हैं। एकल सीड कमांड में आपने इसे दो बार प्रिंट करने के लिए कहा है, प्रत्येक उदाहरण इन-सीटू (या शायद बफर) में मुद्रित होता है। आपको या तो -ई के बजाय पाइप करना होगा या केवल अंतिम पी पर 'पी' लगाना होगा।
माइक्रोबियल

@Rapsey: इस प्रासंगिक बिंदु के बारे में मेरा जवाब देखें
Amessihel

@microbial, यह तब तक काम नहीं करेगा जब अंतिम पी ध्वज अंतिम प्रतिस्थापन अभिव्यक्ति द्वारा प्रत्येक मिलान वाली रेखा पर काम करेगा ।
अम्सीहेल


0

रोपीसी ने कई प्रतिस्थापन अभिव्यक्तियों के बारे में एक प्रासंगिक बिंदु उठाया।

  • सबसे पहले, एक यूनिक्स एसई उत्तर का हवाला देते हुए , आप "उन पंक्तियों को सीमित करने के लिए एक पते के साथ सबसे अधिक sed कमांडों को उपसर्ग कर सकते हैं, जिस पर वे लागू होते हैं"।
  • दूसरा, आप घुंघराले ब्रेस के भीतर समूह बना सकते हैं {}(एक अर्ध-बृहदान्त्र ;या एक नई रेखा के साथ अलग )
  • तीसरा, अंतिम प्रतिस्थापन पर प्रिंट फ्लैग पी जोड़ें

वाक्य - विन्यास:

sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'

उदाहरण ( अधिक विवरण के लिए यहां देखें दस्तावेज़ ):

  • कोड:

    sed -n -e '/^ha/ {s/h/k/gp;s/a/e/g}' <<SAMPLE
    haha
    hihi
    SAMPLE
    
  • परिणाम:

    kaka
    

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.