मैच के बाद अगली लाइन को कैसे grep -v और भी बाहर करें?


15

Grep regex से मेल खाने वाली प्रत्येक पंक्ति के लिए 2 लाइनों को कैसे फ़िल्टर करें?
यह मेरा न्यूनतम परीक्षण है:

SomeTestAAAA
EndTest
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestAABC
EndTest
SomeTestACDF
EndTest

और जाहिर है मैंने कोशिश की जैसे grep -vA 1 SomeTestAAकि जो काम नहीं करता है।

वांछित उत्पादन है:

SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

grep -v 'SomeTextAA' | यूनीक?
DarkHeart

जवाबों:


14

आप (पीसीआरई) के grepसाथ उपयोग कर सकते हैं -P:

grep -P -A 1 'SomeTest(?!AA)' file.txt

(?!AA)शून्य चौड़ाई का नकारात्मक लुकहैड पैटर्न यह सुनिश्चित करता है कि इसके AAबाद नहीं है SomeTest

परीक्षा :

$ grep -P -A 1 'SomeTest(?!AA)' file.txt 
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

डॉट्स के लिए बच चरित्र क्या है? कुछ की तरह।
बेहरोज

1
@Behrooz एस्केप डॉट्स \.तो grep -P -A 1 'SomeTest\.(?!AA)' file.txtयाgrep -P -A 1 'SomeTest(?!\.AA)' file.txt
heemayl

यह इस विशेष मामले में काम करता है क्योंकि ओपी में नमूना रेखाएं जोड़ी जाती हैं SomeTest*\nEndTestइसलिए आप grepमिलान के बाद संदर्भ की एक पंक्ति SomeTest*नहीं बल्कि मिलान वाली सभी पंक्तियों को एक्टली करते हैं SomeTestAA। इनपुट में कुछ और पंक्तियाँ जोड़ें (उदाहरण के लिए foobarप्रत्येक EndTestपंक्ति के बाद एक पंक्ति जोड़ें ) फिर इसे आज़माएँ।
don_crissti

1
@don_crissti यह सच है, मैंने पहले से ही उसके आसपास काम किया है।
बेहरोज

@Behrooz - हमारे साथ साझा करने के लिए परवाह है कि आपने उसके आसपास कैसे काम किया और शायद आपके सवाल के जवाब में मेरी टिप्पणी का जवाब दें?
दान_क्रांति

4

यहां एक sedसमाधान है ( -nयानी कोई ऑटो-प्रिंटिंग नहीं) जो मनमाने इनपुट के साथ काम करता है:

sed -n '/SomeTestAA/!p          # if line doesn't match, print it
: m                             # label m
//{                             # if line matches
$!{                             # and if it's not the last line
n                               # empty pattern space and read in the next line
b m                             # branch to label m (so n is repeated until a
}                               # line that's read in no longer matches) but
}                               # nothing is printed
' infile

तो जैसे इनपुट के साथ

SomeTestAAXX
SomeTestAAYY
+ one line
SomeTestONE
Message body
EndTest
########
SomeTestTWO
something here
EndTest
SomeTestAABC
+ another line
SomeTestTHREE
EndTest
SomeTestAA
+ yet another line

चल रहा है

sed -n -e '/SomeTestAA/!p;: m' -e '//{' -e '$!{' -e 'n;b m' -e '}' -e'}' infile

आउटपुट

SomeTestONE
Message body
EndTest
########
SomeTestTWO
something here
EndTest
SomeTestTHREE
EndTest

यह है, यह बिल्कुल वही लाइनें हटाता है जो चुनेंगी grep -A1 SomeTestAA infile:

SomeTestAAXX
SomeTestAAYY
+ one line
--
SomeTestAABC
+ another line
--
SomeTestAA
+ yet another line

दिलचस्प। मुझे एहसास नहीं था कि //मिलान किया गया था /SomeTestAA/। मैंने सोचा, इस मामले में, यह नकारात्मक अभिव्यक्ति से मेल खाता होगा /SomeTestAA/!:। (+1)
पीटरो।

@ पीटर.ओ - धन्यवाद! नहीं, चश्मा के अनुसार, एक खाली आरई को हमेशा अंतिम कमांड में प्रयुक्त अंतिम आरई से मेल खाना चाहिए ; !का हिस्सा नहीं है फिर , यह एक है sedबात।
don_crissti

3

बहु-पंक्ति क्षेत्रों को एकल रिकॉर्ड के रूप में देखने वाली चीज़ से आपका भाग्य बेहतर हो सकता है। वहाँ एक है sgrepजो मैं ज्यादा इस्तेमाल नहीं किया है।

वहाँ भी awk है, जहाँ आप इनपुट रिकॉर्ड विभाजक सेट कर सकते हैं, और आउटपुट रिकॉर्ड विभाजक, जो भी आपको पसंद है।

pat="^SomeTestAA"
awk  'BEGIN{ RS=ORS="\nEndTest\n"} !/'"$pat/" foo

अधिकांश awk प्रोग्राम सिंगल-कोटेड है, लेकिन मैं अंत में डबल कोट्स में बदल जाता हूं ताकि $patशेल वेरिएबल का विस्तार किया जा सके।


awk -vpat="^SomeTestAA" -vRS="\nEndTest\n" 'BEGIN{ ORS=RS } $0 !~ pat' file
पीटर।

3

एक विकल्प उपयोग करने के लिए है perl compatible regular eहै xpression grep:

pcregrep -Mv 'SomeTestAA.*\n' file

विकल्प -Mपैटर्न को एक पंक्ति में अधिक मिलान करने की अनुमति देता है।


1
@don_crissti दोनों लाइनों को हटा दिया जाएगा। ओपी के विनिर्देश इस मामले को कवर नहीं करते हैं।
जिमीज

यह बिल्कुल स्पष्ट है कि ओपी नमूना और प्रश्न ऐसे मामलों को कवर नहीं करते हैं, मैं यह जानने के लिए उत्सुक हूं कि यह कैसे काम करता है (मैं पीसीआर से परिचित नहीं हूं) क्योंकि उस रेखा की एक विषम संख्या के साथ यह मेल खाता है, यह काम करता है (इसे हटाता है) संदर्भ रेखा भी) और लगातार मेल खाने वाली रेखाओं की संख्या के साथ, यह विफल हो जाती है (यह संदर्भ रेखा को बाद में नहीं हटाती है)।
don_crissti

यह देखते हुए कि (GNU) grepपहले ही PCRE ( -Pविकल्प के माध्यम से ) का समर्थन करता है , उपयोग करने का क्या फायदा है pcregrep?
arielf

@arielf विकल्प का grepसमर्थन नहीं करता -Mहै।
जिमीज

1

आप एक पंक्ति को हटाने के लिए GNU sedके dकमांड का उपयोग कर सकते हैं , और /pat/,+Nपैटर्न और बाद की N लाइनों से मेल खाने वाली लाइनों का चयन करने के लिए इसे उपसर्ग कर सकते हैं। आपके मामले में, N = 1 चूंकि आप केवल एक मिलान रेखा के बाद एकल बाद वाली लाइन को हटाना चाहते हैं:

sed -e '/SomeTestAAAA/,+1d'

1

मानक का उपयोग करना sed:

$ sed '/SomeTestAA/{ N; d; }' file
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

sedस्क्रिप्ट लाइन द्वारा इनपुट फ़ाइल लाइन पार्स करता है, और जब एक लाइन नमूने का मिलान SomeTestAA, दो sedसंपादन आदेशों Nऔर dक्रियान्वित कर रहे हैं। Nआदेश पैटर्न अंतरिक्ष (बफर कि करने के लिए इनपुट की अगली रेखा भी संलग्न sedकर सकते हैं संपादित करें), और dपैटर्न अंतरिक्ष हट जाता है और अगले चक्र शुरू होता है।


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