प्रत्येक grep परिणाम के बाद 2-4 लाइनों को कैसे प्रदर्शित करें?


39

मैं एक मेलबॉक्स फ़ाइल पार्स कर रहा हूं जो असफलता से वितरित ई-मेल के लिए ई-मेल सर्वर रिपोर्ट संग्रहीत करता है। मैं खराब ई-मेल पते निकालना चाहता हूं, ताकि मैं उन्हें सिस्टम से हटा दूं। लॉग फ़ाइल इस तरह दिखती है:

...some content...
                   The mail system

<slavicatomic118@hotmail.com>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)

...some content...
                   The mail system

<oki88@optimumpro.net>: host viking.optimumpro.net[79.101.51.82] said: 550
    Unknown user (in reply to RCPT TO command)

...some content...
                   The mail system

<sigirna_luka@yahoo.com>: host mta5.am0.yahoodns.net[74.6.140.64] said: 554
    delivery error: dd This user doesn't have a yahoo.com account
    (sigirna_luka@yahoo.com) [0] - mta1172.mail.sk1.yahoo.com (in reply to end
    of DATA command)

...etc.

ई-मेल पता "मेल सिस्टम" के साथ एक पंक्ति के बाद 2 लाइनें आती है। इस तरह से grep का उपयोग करने से मुझे "मेल सिस्टम" लाइन और अगली दो लाइनें मिलती हैं:

grep -A 2 "The mail system" mbox_file

हालाँकि, मुझे नहीं पता कि "मेल सिस्टम" लाइन और दूसरी खाली लाइन को इस आउटपुट से कैसे हटाया जाए। मुझे लगता है कि मैं इसे करने के लिए PHP / पर्ल / पायथन स्क्रिप्ट लिख सकता था, लेकिन मुझे आश्चर्य है कि अगर यह grep या किसी अन्य मानक उपकरण के साथ संभव है। मैंने -B पैरामीटर को नकारात्मक ऑफसेट देने की कोशिश की:

grep -A 2 -B -2 "The mail system" mbox_file

लेकिन जीआरपी शिकायत करता है:

grep: -2: invalid context length argument

क्या grep के साथ ऐसा करने का कोई तरीका है?


3
-B अंक को ए-विल के रूप में स्वीकार करता है, और यह मैच से पहले की पिछली पंक्तियों को प्रदर्शित करेगा।
निखिल मुले

3
हाँ, यह सच है, लेकिन मिलान से पहले मिलान में कोई दिलचस्पी नहीं है ... उन्होंने जो समस्या पेश की है, वह यह है कि -ए-बी केवल सकारात्मक मूल्यों को स्वीकार करता है ... और किसी भी मामले में -ए-बी कर सकता है एक दूसरे के सापेक्ष उपयोग नहीं किया जा सकता है, जैसा कि उसने करने का प्रयास किया है।
पीटर

1
हम, सिर्फ यह सुनिश्चित करने के लिए: वे डमी पते हैं जो आपने (सीधे) उस फ़ाइल से नहीं निकाले हैं जो आपको दी गई थी, है ना?
मैथ्यू एम।

1
@ मैथ्यू एम। नहीं, वे असली लॉग फ़ाइल से हैं। मुझे लगा कि चूंकि वे वैसे भी अवैध पते हैं, ऐसे डमी पतों का आविष्कार करने की क्या बात है जो मान्य हो सकते हैं।
मिलान बाबूकोव

जवाबों:


29

grepकेवल इसका उपयोग करके इसे हल करने का सबसे सरल तरीका , grepअंत में एक और उल्टा पाइप करना है । उदाहरण के लिए:

grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v '^\d*$'

28

यदि आप उपयोग करने के लिए बंद नहीं हैं grep, तो प्रयास करें sed...

sed -n '/The mail system/{n;n;p}' 

जब उसे "द मेल सिस्टम" वाली लाइन मिलती है, तो वह अगली लाइन को दो बार पढ़ता है, उसके माध्यम से n;n;, प्रत्येक पिछली पंक्ति को छोड़ देता है क्योंकि वह ऐसा करता है।
यह आपके समूह की तीसरी पंक्ति को पैटर्न स्पेस में छोड़ देता है, जिसे फिर sed के pकमांड के माध्यम से प्रिंट किया जाता है । प्रमुख -nविकल्प अन्य सभी प्रिंटिंग को रोकता है।

अगली दो पंक्तियों को भी प्रिंट करने के लिए, यह केवल अगले का मामला है औरn;p दो बार और प्रिंट करें

sed -n '/The mail system/{n; n;p; n;p; n;p}'   

अगली पंक्ति आपके द्वारा अपेक्षित लाइनों के लिए पढ़ी जा सकती है और एक एकल ब्लॉक को केवल एक के साथ जमा किया जा सकता है p... Nअगली पंक्ति को पढ़ता है और इसे पैटर्न स्पेस में जोड़ता है,

यहाँ अंतिम संघनित संस्करण है ...

sed -n '/The mail system/{n;n;N;N;p}'   

यदि आप एक ग्रुप सेपरेटर चाहते हैं , जो कि grep wouuld आउटपुट के समान है, तो आप sed के इन्सर्ट कमांड i(जो एक लाइन पर अंतिम कमांड होना चाहिए) का उपयोग कर सकते हैं ...

यहाँ एक समूह सेपरेटर शामिल करने के लिए वाक्यविन्यास है

sed -n '/The mail system/{n;n;N;N;p;i--
       }' > output-file  # or | ...

यहाँ पहले मैच के लिए आउटपुट है:

<slavicatomic118@hotmail.com>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)                                                                    
--

+1। धन्यवाद। मुझे इस मामले में इसकी आवश्यकता नहीं है, लेकिन मैं इस बुकमार्क को संभालकर रखने के मामले में अधिक जटिल सामान रखूँगा।
मिलान बाबूसकोव

यह एक महान जवाब है!
dotancohen

9
grep -A 2 -B -2 "The mail system" mbox_file

-B पिछली पंक्तियों के लिए है, इसलिए -negative value देने की कोई आवश्यकता नहीं है।

grep -A 2 -B 2 "The mail system" mbox_file   # This will work please check

इस सवाल का जवाब नहीं है। -A 2 -B 2संदर्भ से पहले 2 लाइनों के संदर्भ में 2 लाइनों से प्रिंट करता है। सवाल संदर्भ के बाद 4 लाइनों के संदर्भ में 2 लाइनों से छपाई के बारे में है।
daniel.neumann 14

1

मुझे केवल grep (s) का उपयोग करने का कोई मतलब नहीं है, सिवाय इसके कि वह एक सख्त बाधा है। यह grep के लिए एक कॉल के साथ नहीं किया जा सकता है।

grep -A 2 "The mail system" mbox_file | tail -n +3
  • grep: लाइन और आउटपुट 2 लाइनों का पता लगाएं,
  • पूंछ: पहले 2 लाइनों (यानी तीसरी लाइन से शुरू) में कटौती।

2
यह केवल तभी काम करता है जब एक एकल मिलान रेखा होती है, जो संभवतः वह नहीं है जो सवाल पूछ रहा है।
jw013

यह कुछ भी नहीं है जो प्रश्न के लिए पूछा गया है, लेकिन यह मेरी वर्तमान स्थिति में मेरी मदद करता है :-)।
daniel.neumann 14

1
@ daniel.neumann मुझे पता है, लेकिन मैं बिल्कुल आपके जूतों में था और सोचा था कि दूसरों के गूगल-फू का नेतृत्व भी यहां होगा।
TWStStrrob

0

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

perl -ne 'print if( (/The mail system/ && ($end=1))..!$end-- )' 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.