ambil "istilah" dan kecualikan "istilah lain"

28

Saya mencoba membangun pencarian grep yang mencari istilah tetapi tidak termasuk baris yang memiliki istilah kedua. Saya ingin menggunakan beberapa -e "pattern"opsi tetapi itu tidak berhasil.

Ini adalah contoh dari perintah yang saya coba dan pesan kesalahan yang dihasilkannya.

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

Menurut saya itu -vberlaku untuk semua istilah / pola pencarian. Karena ini berjalan tetapi kemudian tidak termasuk search termdalam hasil.

grep -i -E "search term" -ve "exclude term"
nelaaro
sumber
Apakah ada opsi lain untuk dikecualikan, karena kadang-kadang kita harus menangkap garis di sekitar kata dan Jika kita mengecualikan dalam operasi berikutnya menggunakan '|' , itu hanya menghilangkan kata itu tetapi tidak menghapus blok untuk kata itu
Learner

Jawaban:

40

Ke dan ekspresi dengan grep Anda memerlukan dua pemanggilan:

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

Jika istilah yang Anda cari bukan ekspresi reguler, gunakan pencocokan string tetap ( -F) yang lebih cepat:

grep -F "search term" | grep -Fv "exclude term"
Thor
sumber
18

Tanpa memohon grep dua kali, hanya ada satu cara yang bisa saya pikirkan untuk mencapai ini. Ini melibatkan Perl Compatible Regular Expressions (PCRE) dan beberapa pernyataan yang agak membingungkan .

Untuk mencari foo mengecualikan kecocokan yang mengandung bilah , Anda dapat menggunakan:

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

Begini cara kerjanya:

  • (?!bar)cocok dengan apa pun yang tidak bar tanpa menggunakan karakter dari string. Kemudian .mengkonsumsi satu karakter.

  • ^((?!bar).)*ulangi di atas dari awal string ( ^) ke akhir ( $). Ini akan gagal jika barditemui pada titik tertentu, karena (?!bar)tidak akan cocok.

  • (?=^((?!bar).)*$) pastikan string cocok dengan pola sebelumnya, tanpa mengkonsumsi karakter dari string.

  • foomencari foo seperti biasa.

Saya menemukan retasan ini dalam ekspresi Reguler untuk mencocokkan string yang tidak mengandung kata? . Dalam jawaban Bart Kiers , Anda dapat menemukan penjelasan yang jauh lebih rinci tentang bagaimana pandangan negatif beroperasi.

Dennis
sumber
Retas yang bagus. Trik ini juga berfungsi di Jawa, btw.
Raman
12

Jika Anda ingin melakukan ini dalam satu pass, Anda dapat menggunakan awk alih-alih grep.

Format:

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

Contoh:

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

Tidak menghasilkan apa-apa.

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

Pengembalian: halo thre

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

Tidak menghasilkan apa-apa.

Untuk beberapa pola, Anda bisa menggunakan tanda kurung untuk mengelompokkannya.

Contoh:

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

Pengembalian: halo thre

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

Pengembalian: hi thre

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

Tidak menghasilkan apa-apa.

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

Tidak menghasilkan apa-apa.

Philip Reese
sumber
1
Ini bekerja untuk saya, tetapi saya kehilangan warna = P
Leopoldo Sanczyk
1
Warna dari keluaran apa? Jika Anda mencoba mempertahankan warna dengan ls, gunakan argumen "--color = always" setiap kali menguraikan output (atau Anda biasanya akan selalu kehilangan warna saat mem-parsing teks). Contoh: ls --color=always | awk '/hello/ && !/goodbye/'
Philip Reese
Terima kasih atas jawabannya @Philip! Saya sudah mencobanya sebelumnya, tetapi tidak berhasil. Saya kira karena polanya memiliki teks berwarna, maka tidak cocok lagi nanti, dan saya harus memasukkan semacam kode warna dalam polanya. Bagaimanapun, milik Anda adalah cara tercepat yang saya temukan untuk dilakukan grep -Rdalam beberapa file kode menggunakan baris perintah Ubuntu.
Leopoldo Sanczyk
1

Dari eksperimen saya, tidak ada masalah untuk membuat banyak perbedaan jika Anda mengirimkan istilah pengecualian melalui grepatau sed. Sed memiliki beberapa fitur penggantian teks berguna lainnya yang sering saya gunakan untuk lebih memfilter put file log. Jadi saya akan menggunakan sed karena saya menggabungkan sejumlah filter pada sed.

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

 / usr / bin / waktu grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login kedaluwarsa / d" | toilet
24.05user 0.15sistem 0: 25.27menghapus CPU 95% (0avgtext + 0avgdata 3504maksresiden) k
0input + 0outputs (0major + 246minor) kesalahan halaman 0swaps
   5614 91168 1186298

 / usr / bin / waktu grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login kedaluwarsa / d" | toilet
23.50 pengguna 0.16sistem 0: 24.48menghapuskan CPU 96% (0avgteks + 0avgdata 3504maksresiden) k
0input + 0outputs (0major + 246minor) kesalahan halaman 0swaps
   5614 91168 1186298

 / usr / bin / waktu grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login kedaluwarsa" | toilet
23.08pengguna 0.14sistem 0: 23.55menghapus CPU 98% (0avgtext + 0avgdata 3504maksresiden) k
0input + 0outputs (0major + 246minor) kesalahan halaman 0swaps
   5614 91168 1186298

 / usr / bin / waktu grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login kedaluwarsa" | toilet
23.50 pengguna 0.15sistem 0: 25.27menghapuskan CPU 93% (0avgtext + 0avgdata 3488maxresident) k
0input + 0outputs (0major + 245minor) kesalahan halaman 0swaps
   5614 91168 1186298

nelaaro
sumber
3
Coba bandingkan runtime grep -Falih - alih grep -Edan jangan gunakan -ijika Anda tidak membutuhkannya.
Thor
1
Tapi kemudian Anda tidak memberikan contoh menggunakan sed;)
Benjamin R