Jak odfiltrować 2 linie dla każdej linii pasującej do wyrażenia regularnego grep?
to mój minimalny test:
SomeTestAAAA
EndTest
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestAABC
EndTest
SomeTestACDF
EndTest
I oczywiście próbowałem np. grep -vA 1 SomeTestAA
Które nie działa.
pożądana wydajność to:
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest
text-processing
grep
Behrooz
źródło
źródło
Odpowiedzi:
Możesz używać
grep
z-P
(PCRE):(?!AA)
jest ujemnym wzorem wyprzedzającym o zerowej szerokości, zapewniającym, że nie będzieAA
po nimSomeTest
.Test:
źródło
\.
sogrep -P -A 1 'SomeTest\.(?!AA)' file.txt
lubgrep -P -A 1 'SomeTest(?!\.AA)' file.txt
SomeTest*\nEndTest
dzięki czemu można pingowaćgrep
wszystkie pasujące linie,SomeTest*
ale nieSomeTestAA
+ jedna linia kontekstu po dopasowaniu. Dodaj więcej linii do wejścia (np. Dodaj linięfoobar
po każdejEndTest
linii), a następnie spróbuj ponownie.Oto
sed
rozwiązanie (-n
bez automatycznego drukowania), które działa z dowolnymi danymi wejściowymi:więc z wejściem jak
bieganie
wyjścia
to znaczy usuwa dokładnie linie,
grep -A1 SomeTestAA infile
które wybrałyby:źródło
//
dopasowane/SomeTestAA/
. Myślałem, że w tym przypadku byłoby to pasowało do zanegowane wyrażenie:/SomeTestAA/!
. (+1)!
nie jest częścią RE , jest tosed
sprawa.Możesz mieć więcej szczęścia z czymś, co wygląda na regiony wieloliniowe jako pojedyncze rekordy. Jest taki, z
sgrep
którego nie korzystałem wiele.Istnieje również awk, w którym możesz ustawić separator rekordów wejściowych i separator rekordów wyjściowych na cokolwiek zechcesz.
Większość programu awk jest pojedynczego cudzysłowu, ale zmieniam na podwójne cudzysłowy na końcu, aby
$pat
zmienną powłoki można było rozwinąć.źródło
awk -vpat="^SomeTestAA" -vRS="\nEndTest\n" 'BEGIN{ ORS=RS } $0 !~ pat' file
Jedną z opcji jest użycie
p
Erlc
ompatibler
egulare
Xpressiongrep
:Ta opcja
-M
pozwala dopasować wzór do więcej niż jednej linii.źródło
grep
już obsługuje PCRE (poprzez-P
opcję), jaka jest korzyść z używaniapcregrep
?grep
nie obsługuje-M
opcji.Możesz użyć polecenia GNU
sed
,d
aby usunąć linię i poprzedzić ją znakiem,/pat/,+N
aby wybrać linie pasujące do wzorca i kolejnych N linii. W twoim przypadku N = 1, ponieważ chcesz usunąć tylko jedną kolejną linię po pasującej linii:źródło
Za pomocą standardowego
sed
:sed
Skrypt analizuje wiersz po wierszu pliku wejściowego, a gdy linia pasuje do wzorcaSomeTestAA
, dwased
polecenia edycjiN
id
są wykonywane.N
Polecenie dołącza następną linię wejścia do przestrzeni wzorca (buforze tymsed
można edytować) id
usuwa przestrzeń wzór i rozpoczyna następny cykl.źródło
Wypróbowałem komendę Below sed i działało dobrze
Komenda
wynik
źródło