“terim” için grep ve “başka terim” hariç


28

Terim arayan, ancak ikinci terim içeren satırları hariç tutan bir grep araması yapmaya çalışıyorum. Birden çok -e "pattern"seçenek kullanmak istedim ancak bu işe yaramadı.

İşte denediğim bir komutun örneği ve oluşturduğu hata mesajı.

grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory

-vTüm arama terimleri / kalıpları için geçerli olduğunu bana söylüyor . Bu çalışır ancak sonra search termsonuçlara dahil değildir .

grep -i -E "search term" -ve "exclude term"

Hariç tutulacak başka bir seçenek var mı, çünkü bazen bir kelimenin etrafında satırlar çizmeliyiz ve sonraki işlemde '|' kullanarak dışlarsak , sadece bu sözcüğü kaldırır, ancak o kelimenin bloğunu kaldırmaz
Öğrenci

Yanıtlar:


40

Kime ve grep ifadeleri için iki çağrı yapmanız gerekir:

grep -Ei "search term" | grep -Eiv "exclude term"

Aradığınız terimler normal ifadeler değilse -F, daha hızlı olan sabit dize matching ( ) kullanın :

grep -F "search term" | grep -Fv "exclude term"

18

Grep'i iki kez çağırmak yerine, bunu başarmanın tek bir yolu var. Bu içerir Perl Uyumlu Normal İfadeleri (PCRE) ve bazı oldukça hacky görünüm etrafında iddialarını .

Çubuk içeren eşleşmeleri hariç foo aramak için kullanabilirsiniz:

grep -P '(?=^((?!bar).)*$)foo'

İşte nasıl çalışıyor:

  • (?!bar)değil her şeye uyar bar dizeden karakterleri tüketmeden. Sonra .tek bir karakter tüketir.

  • ^((?!bar).)*( ^) dizgenin başlangıcından sonuna ( $) sonuna kadar tekrarlar . barHerhangi bir noktada karşılaşılırsa başarısız olur , çünkü (?!bar)eşleşmeyecektir.

  • (?=^((?!bar).)*$) dizgiden karakter tüketmeden dizgenin önceki desenle eşleştiğinden emin olur.

  • foofoo'yu her zamanki gibi arar .

Bu hack Düzenli ifadede bir kelime içermeyen dize eşleştirmek için bulundu ? . In Bart Kiers' cevabı , negatif ileriye bakma nasıl çalıştığını çok daha ayrıntılı bir açıklama bulabilirsiniz.


Güzel kesmek. Bu numara Java'da da çalışıyor, btw.
Raman

12

Bunu bir seferde yapmak istiyorsanız grep yerine awk kullanabilirsiniz.

Biçim:

echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'

Örnekler:

  • echo "hello there" | awk '/hello/ && !/there/'

Hiçbir şey döndürmez.

  • echo "hello thre" | awk '/hello/ && !/there/'

Döner: merhaba

  • echo "hllo there" | awk '/hello/ && !/there/'

Hiçbir şey döndürmez.

Birden fazla desen için, bunları gruplamak için parantez kullanabilirsiniz.

Örnekler:

  • echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'

Döner: merhaba

  • echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'

İade: merhaba

  • echo "hello there" | awk '(/hello/ || /hi/) && !/there/'

Hiçbir şey döndürmez.

  • echo "hi there" | awk '(/hello/ || /hi/) && !/there/'

Hiçbir şey döndürmez.


1
Benim için işe yaradı, ama renkleri kaybettim = P
Leopoldo Sanczyk

1
Hangi çıktıdan renkler? Renkleri ls ile korumaya çalışıyorsanız, çıktıyı ayrıştırırken "--color = always" bağımsız değişkenini kullanın (veya metni ayrıştırırken normalde renkleri her zaman kaybedersiniz). Örnek: ls --color=always | awk '/hello/ && !/goodbye/'
Philip Reese

Cevap @Philip için teşekkürler! Bunu daha önce denedim, ama başarılı olamadım. Desen renkli metne sahip olduğundan, daha sonra uyuşmadığını ve desene bir tür renk kodu eklemem gerektiğini tahmin ediyorum. Her neyse, seninki grep -RUbuntu komut satırını kullanarak birkaç kod dosyasında bulduğum en hızlı yol .
Leopoldo Sanczyk

1

Yaptığım deneylerden, dışlama terimlerinizi grepveya aracılığıyla aktarırsanız, çok fazla fark yaratmak için dikiş atılmaz sed. Sed, günlük dosyalarının daha iyi filtrelenmesini sağlamak için sık sık kullandığım bazı yararlı metin değiştirme özelliklerine sahiptir. Bu yüzden sed'i oldukça fazla sayıda filtre birleştirdiğim için sed kullanacağım.

wc /var/log/tomcat/tomcat.2013-01-14.log.1 
  1851725

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ giriş tamam / d" -e "/ Giriş süresi doldu / d" | tuvalet
24.05 kullanıcı 0.15sistem 0: 25.27,% 95 CPU (0avgtext + 0avgdata 3504maxresident) kullanılan
0 giriş + 0 çıkış (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ giriş tamam / d" -e "/ Giriş süresi doldu / d" | tuvalet
23.50 kullanıcı 0.16 sistem 0: 24.48,% 96 CPU (0avgtext + 0avgdata 3504maxresident) k
0 giriş + 0 çıkış (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "giriş tamam" -e "Giriş süresi doldu" | tuvalet
23.08 kullanıcı 0.14sistem 0: 23.55,% 98 CPU'yu buldu (0avgtext + 0avgdata 3504maxresident) k
0 giriş + 0 çıkış (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "giriş tamam" -e "Giriş süresi doldu" | tuvalet
23.50 kullanıcı 0.15sistem 0: 25.27,% 93 CPU alındı ​​(0avgtext + 0avgdata 3488maxresident) k
0inputs + 0outputs (0major + 245minor) pagefaults 0swaps
   5614 91168 1186298


3
grep -FBunun yerine çalışma zamanını karşılaştırmayı deneyin grep -Eve -iihtiyacınız yoksa kullanmayın .
Thor

1
Ama sonra kullanarak örnekler sed
Benjamin R
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.