Grep regex Dize İÇERMEZ


182

grepBir syslog dosyasına karşı kontrol etmek için normal ifade desenleri listesi geçiriyorum. Genellikle bir IP adresi ve günlük girişi ile eşleşirler;

grep "1\.2\.3\.4.*Has exploded" syslog.log

Bu sadece bir "1\.2\.3\.4.*Has exploded"döngü içinde geçmekte olduğum kısım gibi desenlerin bir listesi , bu yüzden örneğin "-v" yi geçemiyorum.

Yukarıdakilerin tersini yapmaya çalışırken kafam karıştı, belirli bir IP adresi ve hatayla eşleşmeyen bir NOT eşleşmesi "! . Ben olmalıdır maç DEĞİL bir IP ekleyemeyebiliriz.

StackOverflor üzerinde çeşitli benzer mesajlar gördüm, ancak onlar ile çalışmak gibi olamaz regex desenleri kullanın grep. Herkes greplütfen çalışma örneği verebilir mi?

GÜNCELLEME: Bu böyle bir senaryoda oluyor;

patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
do
 grep "${patterns[$i]}" logfile.log
done

Bazen bir deseni eşleştirmek istediğiniz anlamına gelir , ancak diğer zamanlarda belirli bir desen dışındaki her şeyi eşleştirmek ister misiniz ? (bu tuhaf bir gereklilik gibi görünüyor, ama her neyse). Bu durumda, neden iki farklı desen listesini tekrarlamıyorsunuz?
beerbajay

Regex hakkında çok bilgili değilim; Her kayıt cihazı hakkında bunu bilmek istemediğim için "Exploded Has" için grep istemiyorum, bu yüzden bir şekilde "Exploded Has" ve! 9.10.11.12 için bir şekilde grep?
jwbensley

Kesinlikle bir ifadede yapmanız gerekiyorsa, Neil'in önerdiği gibi olumsuz bakışlar gitmenin yoludur. Yorumuma bakın.
beerbajay

@Neil'in cevabına göre PCRE tarzı normal ifade eşleştirmesi ve negatif bir ileriye dönük iddiası patterns[3]="\!9\.10\.11\.12.*Has exploded"kullanın : PCRE'deki değişiklikler patterns[3]="(?<!9\.10\.11\.12).*Has exploded"ve PCRE'deki grep "${patterns[$i]}" logfile.logdeğişiklikler grep -P "${patterns[$i]}" logfile.logvarsayılan olarak daha fazla meta karakter kabul eder, bu nedenle kaçışların bazı eşleşen ifadelerden kaldırılması gerekebilir.
Codex24

Yanıtlar:


342

grepeşleşir, grep -vtersini yapar. "A ile B'yi eşleştirmeniz" gerekiyorsa, genellikle borular kullanırsınız:

grep "${PATT}" file | grep -v "${NOTPATT}"

Bu, bahsettiğim gibi bir döngünün ortasına gidiyor ve sadece DESEN'i grep'e geçiyorum, böylece bahsettiğim gibi "-v" kullanamıyorum. Ben sadece bir desen listesi döngü ve grep geçiyor.
jwbensley

1
Gerçekten kullanabilirsiniz -vve bir döngüde kullanabilirsiniz. Belki de sınırlamalarınız hakkında daha spesifik olmanız ya da senaryonuzun nasıl çalışması gerektiği konusunda yanlış bir fikriniz var. Bir kod göndermeyi deneyin.
beerbajay

Teşekkürler beerbajay, bazı bağlam vermek için orijinal gönderiye kesilmiş bir kod ekledim. Ne demek istediğimi anlıyor musun?
jwbensley

Bu cevap tamamen doğru değil ama hemen hemen beerbajay yazdınız, döngüyü yeniden düşünmem ve sonunda -v kullanmam gerekiyordu. İşaretçi için teşekkürler;)
jwbensley

1
Peki ya A B'den oluşuyorsa? Başka bir deyişle, beraber hatları maç ne isterseniz hiçbir A ve AB ile hatlar? Bir boru çalışmaz.
pawamoy

15
(?<!1\.2\.3\.4).*Has exploded

Negatif gözbebeküne (Perl düzenli ifadesi) sahip olmak için bunu -P ile çalıştırmanız gerekir, bu yüzden komut:

grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log

Bunu dene. Önceden varsa çizgiyi görmezden gelmek için negatif gözetleme kullanır 1.2.3.4. Umarım yardımcı olur!


1
Eminim, grepetrafındaki görüşü desteklemiyor. Gnu grepkullanmadığınızda ve --Pparametreyi bir PCRE motoru kullanması için kullanmadığınız sürece .
Tim Pietzcker

Hayır, grep bu tür Regex'i desteklemez; $ grep -P (? <\! 1 \ .2 \ .3 \ .4) test.log -bash: beklenmeyen belirtecin yanında sözdizimi hatası `('
jwbensley

Kabuk tarafından yorumlanacak karakterler içeriyorsa normal ifadeyi alıntılamanız gerekir.
beerbajay

doğru alıntı: grep -P '(?<!1\.2\.3\.4) Has exploded' test.logLookbehind ifadesinin yalnızca ifadenin eşleşen kısmından hemen önceki karakterlerde çalıştığını unutmayın; bu nedenle adres ve mesaj arasında başka şeyler varsa, örneğin 1.2.3.4 FOO Has explodedbu işe yaramaz.
beerbajay

@ Timpietzcker, çok dikkatli. Bunu soruya ekleyeceğim. Ayrıca, .*örneğinde de olduğu için olumsuz bir bakıştan sonra bir tane olduğunu lütfen unutmayın, aralarında başka bir metin olabileceğini hayal ediyorum.
Neil

2
patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
 do
grep "${patterns[$i]}" logfile.log
done

ile aynı olmalı

egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"    
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.