Pencocokan negatif menggunakan grep (garis kecocokan yang tidak mengandung foo)

991

Saya telah mencoba mencari sintaks untuk perintah ini:

grep ! error_log | find /home/foo/public_html/ -mmin -60

ATAU:

grep '[^error_log]' | find /home/baumerf/public_html/ -mmin -60

Saya perlu melihat semua file yang telah dimodifikasi kecuali untuk yang bernama error_log.

Saya sudah baca di sini , tetapi hanya menemukan satu notpola regex.

jerrygarciuh
sumber
13
[^ error_log] tidak akan pernah berhasil, [] adalah kelas char, regexp pada umumnya tidak bagus pada pola negatif (kecuali mesin mengimplementasikan lookaheads negatif).
Jaap

Jawaban:

1758

grep -v adalah temanmu:

grep --help | grep invert  

-v, --invert-match pilih jalur yang tidak cocok

Lihat juga yang terkait -L(pelengkap dari -l).

-L, --files-without-match hanya mencetak nama FILE yang tidak mengandung kecocokan

Motti
sumber
125
Patut disebutkan bahwa untuk beberapa -epilihan pertandingan (negatif) dapat digunakan:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan
31
Mirip dengan komentar dari @ Babken-Vardanyan Also - mampu menggunakan pipa untuk bergabung dengan beberapa pertandingan misalnyagrep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams
13
Komentar terakhir TIDAK sama dengan akan mencari hal-hal yang tidak cocok dengan keduanya daripada keduanya. yaitu Jika cocok satu tetapi tidak yang lain masih dicetak. Cobalah keduanya dengan string yang tidak serupa
Evan Langlois
7
@EvanLanglois - memaksa grep untuk menginterpretasikan pola sebagai ekspresi reguler yang diperluas menggunakan -Ekarya, yaitu grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini
1
@ OlleHärstedt, saya pikir saya salah mengerti skenario Anda di komentar saya sebelumnya, berikut ini mungkin apa yang Anda cari grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( mengapa grep pertama?, Selalu ada jalannya :))
Motti
139

Anda juga dapat menggunakan awkuntuk tujuan ini, karena memungkinkan Anda untuk melakukan pemeriksaan yang lebih kompleks dengan cara yang lebih jelas:

Baris tidak mengandung foo:

awk '!/foo/'

Baris yang mengandung tidak foojuga bar:

awk '!/foo/ && !/bar/'

Baris yang tidak mengandung fooatau baryang mengandung salah satu foo2atau bar2:

awk '!/foo/ && !/bar/ && (/foo2/ || /bar2/)'

Dan seterusnya.

fedorqui 'SO berhenti merugikan'
sumber
2
Itu sebenarnya cukup keren. Anda bahkan tidak perlu mempelajari bahasa awk lengkap untuk mengelompokkan regexp dengan operator logis. Terima kasih atas jawaban ini!
Peter T.
1
Persis apa yang saya cari, terima kasih banyak.
mmrs151
13

Dalam kasus Anda, Anda mungkin tidak ingin menggunakan grep, tetapi tambahkan klausa negatif pada perintah find, mis

find /home/baumerf/public_html/ -mmin -60 -not -name error_log

Jika Anda ingin memasukkan wildcard dalam nama, Anda harus menghindarinya, misalnya untuk mengecualikan file dengan akhiran .log:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
Papa Smurf
sumber