-V nasıl grep ve maçtan sonraki sonraki satırı nasıl hariç tutar?


15

Grep normal ifadesiyle eşleşen her satır için 2 satır nasıl filtrelenir?
bu benim minimal test:

SomeTestAAAA
EndTest
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestAABC
EndTest
SomeTestACDF
EndTest

Ve tabii ki denedim, grep -vA 1 SomeTestAAki bu işe yaramıyor.

istenen çıktı:

SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

grep -v 'SomeTextAA' | uniq?
DarkHeart

Yanıtlar:


14

(PCRE) grepile kullanabilirsiniz -P:

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

(?!AA)orada hiçbir sağlanması sıfır genişliği negatif ileri yönlü desen AAsonra SomeTest.

Ölçek :

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

noktalar için kaçış karakteri nedir? Some.Test.AA gibi mi?
Behrooz

1
@Behrooz Kaçış noktaları \.so grep -P -A 1 'SomeTest\.(?!AA)' file.txtorgrep -P -A 1 'SomeTest(?!\.AA)' file.txt
heemayl

Bu özel durumda çalışır çünkü OP'lerde örnek satırlar çift olarak gelir, SomeTest*\nEndTestböylece grepeşleşen tüm satırlara ping uygularsınız SomeTest*ancak SomeTestAAmaçtan sonra + bir bağlam satırına değil . Girişe biraz daha satır ekleyin (örneğin foobarher EndTestsatırdan sonra bir satır ekleyin ) ve tekrar deneyin.
don_crissti

1
@don_crissti bu doğru, ben zaten bunun etrafında çalıştım.
Behrooz

@Behrooz - bu konuda nasıl çalıştığınızı bizimle paylaşmak ister ve belki de sorunuzun altındaki yorumuma cevap verir misiniz?
don_crissti

4

Rasgele girdi ile çalışan bir sedçözüm ( -nyani otomatik yazdırma olmadan):

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

yani bir girdi ile

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

çalışan

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

çıktılar

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

yani, tam olarak grep -A1 SomeTestAA infileseçecek çizgileri kaldırır :

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

İlginç. Bunu fark etmedi //eşleşti /SomeTestAA/. Bu durumda, reddedildiği ifade eşleşti olurdu, düşündü: /SomeTestAA/!. (+1)
Peter.O

@ Peter.O - teşekkürler! Hayır, teknik özelliklere göre, boş bir RE her zaman son komutta kullanılan son RE ile eşleşmelidir ; !parçası değildir RE , şey sedşey.
don_crissti

3

Çok satırlı bölgelere tek kayıt olarak bakan bir şeyde daha iyi şansınız olabilir. Çok sgrepkullanmadığım bir şey var.

Giriş kayıt ayırıcısını ve çıkış kayıt ayırıcısını istediğiniz gibi ayarlayabileceğiniz awk de var.

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

Awk programının çoğu tek tırnaklı, ancak sonunda $patkabuk değişken genişletilebilir böylece çift tırnak değiştirin .


awk -vpat="^SomeTestAA" -vRS="\nEndTest\n" 'BEGIN{ ORS=RS } $0 !~ pat' file
Peter.O

3

Seçeneklerden biri kullanımda olan perl compatible regular eXPression grep:

pcregrep -Mv 'SomeTestAA.*\n' file

Bu seçenek -M, desenin bir satırdan fazla eşleşmesine izin verir.


1
@don_crissti Her iki satır da kaldırılacak. OP'nin belirtimi bu durumu kapsamaz.
jimmij

OP örnek ve sorusunun bu tür vakaları kapsamadığı oldukça açıktır, bunun nasıl çalıştığını merak ediyorum (pcre'ye aşina değilim), çünkü eşleşen bir dizi ardışık satırla, bu çalışıyor (kaldırıyor bağlam satırı da) ve eşleşen birkaç ardışık satırla başarısız olur (daha sonra bağlam satırını kaldırmaz).
don_crissti

(GNU) ' grepun zaten PCRE'yi ( -Pseçenek üzerinden ) desteklediği göz önüne alındığında , kullanmanın avantajı pcregrepnedir?
arielf

@arielf seçeneği grepdesteklemiyor -M.
jimmij

1

Sen GNU kullanabilirsiniz sed'ın dbir satır silmek komutu ve önekini /pat/,+Ndesen ve sonraki eşleşen satırları seçmek için N hatları. Sizin durumunuzda, N = 1 , sadece eşleşen bir satırdan sonra gelen sonraki satırı silmek istediğiniz için:

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

1

Standart kullanarak sed:

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

sedKomut hattı ile girdi dosya hattı ayrıştırır ve bir hat paterni eşleştiğinde SomeTestAA, iki seddüzenleme komutlarını Nve dçalıştırılır. NKomut model alanı (yani tampon girişi bir sonraki satıra ekler sedkutu düzenlemek) ve dmodel alanı silinir ve bir sonraki döngü başlar.


1

Below sed komutu ile denedim ve iyi çalıştı

komuta

sed  '/SomeTestAA/,+1d' filename

çıktı

SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.