Hitung semua kemunculan string dalam banyak file dengan grep


289

Saya punya banyak file log. Saya perlu mencari tahu berapa kali sebuah string muncul di semua file.

grep -c string *

kembali

...
file1:1
file2:0
file3:0
...

Menggunakan pipa saya hanya bisa mendapatkan file yang memiliki satu atau lebih kejadian:

grep -c string * | grep -v :0

...
file4:5
file5:1
file6:2
...

Bagaimana saya bisa mendapatkan hanya jumlah gabungan? (Jika kembali file4:5, file5:1, file6:2, saya ingin kembali 8.)


1
Bisakah Anda memberi tahu saya apa yang dilakukan grep -v: 0? . Saya tahu ini penting untuk file yang memiliki kejadian lebih besar dari 0. Apa maksud opsi -v dan: 0? Mohon beritahu saya.
Gautham Honnavara

@GauthamHonnavara grep: 0 mencari garis yang cocok dengan string: 0. -v adalah opsi untuk membalikkan pencarian itu jadi alih-alih menggunakan grep -v: 0 berarti menemukan semua baris yang tidak mengandung: 0 sehingga baris dengan file4: 5 dan file27: 193 semua akan melewati karena mereka tidak mengandung: 0
penguin359

Anda dapat memilih banyak file menggunakan ruang. grep file1 file2 --options
Dnyaneshwar Harer

Jawaban:


288
cat * | grep -c string

9
Ini memiliki batasan yang sama dengan menghitung beberapa kejadian pada satu baris hanya sekali. Saya menduga perilaku ini tidak masalah dalam kasus ini.
Michael Haren

@Michael Haren Ya, hanya ada satu kemunculan string dalam satu baris.
Željko Filipin

2
Saya lebih suka melakukannya grep -c string<*Jadi hanya mengganti ruang dengan kurang dari.
JamesM-SiteGen

48
Tidak membahas beberapa kejadian secara
berurutan

2
Ini tidak berfungsi jika Anda ingin mencari di subdirektori juga, sedangkan grep -odan wc -lmemang. kucing lebih cepat dalam kasus-kasus seperti pertanyaan aslinya.
Leagsaidh Gordon

296

Ini berfungsi untuk beberapa kejadian per baris:

grep -o string * | wc -l

2
Ini juga bekerja: grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
seorang coder

2
grep -ioR string * | wc -ladalah apa yang saya gunakan untuk melakukan pencarian case-insensitive, recursive, only-matching
LeonardChallis

2
Yang ini menunjukkan file yang relevan dan kemudian jumlah total kecocokan:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron

28
grep -oh string * | wc -w

akan menghitung banyak kemunculan dalam satu baris


24
grep -oh "... my that curry was strong" * >> wc:)
icc97

23

Alih-alih menggunakan -c, hanya pipa itu ke wc -l.

grep string * | wc -l

Ini akan membuat daftar setiap kemunculan pada satu baris dan kemudian menghitung jumlah baris.

Ini akan melewatkan contoh di mana string muncul 2+ kali pada satu baris.


2
Perpipaan ke "wc-l" juga bekerja dengan baik bersama "grep -r 'test'." yang memindai secara rekursif semua file untuk string 'test' di semua direktori di bawah ini.
stevek


9

Sesuatu yang berbeda dari semua jawaban sebelumnya:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *

senang melihat pendekatan yang tidak menggunakan grep, esp karena grep saya (di windows) tidak mendukung opsi -o.
David Roussel

9

Anda dapat menambahkan -Runtuk mencari secara rekursif (dan menghindari menggunakan cat) dan -Imengabaikan file biner.

grep -RIc string .

7

Solusi AWK wajib:

grep -c string * | awk 'BEGIN{FS=":"}{x+=$2}END{print x}'

Berhati-hatilah jika nama file Anda menyertakan ":".


5

Solusi AWK yang juga menangani nama file termasuk titik dua:

grep -c string * | sed -r 's/^.*://' | awk 'BEGIN{}{x+=$1}END{print x}'

Perlu diingat bahwa metode ini masih tidak menemukan banyak kemunculan stringpada baris yang sama.


4

Jika Anda ingin jumlah kemunculan per file (contoh untuk string "tcp"):

grep -RIci "tcp" . | awk -v FS=":" -v OFS="\t" '$2>0 { print $2, $1 }' | sort -hr

Contoh output:

53  ./HTTPClient/src/HTTPClient.cpp
21  ./WiFi/src/WiFiSTA.cpp
19  ./WiFi/src/ETH.cpp
13  ./WiFi/src/WiFiAP.cpp
4   ./WiFi/src/WiFiClient.cpp
4   ./HTTPClient/src/HTTPClient.h
3   ./WiFi/src/WiFiGeneric.cpp
2   ./WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino
2   ./WiFiClientSecure/src/ssl_client.cpp
1   ./WiFi/src/WiFiServer.cpp

Penjelasan:

  • grep -RIci NEEDLE . - mencari string NEEDLE secara rekursif dari direktori saat ini (mengikuti symlink), mengabaikan binari, menghitung jumlah kemunculan, mengabaikan case
  • awk ... - perintah ini mengabaikan file dengan nol kejadian dan memformat garis
  • sort -hr - mengurutkan garis dalam urutan terbalik dengan angka di kolom pertama

Tentu saja, ia bekerja dengan perintah grep lainnya dengan opsi -c(hitung) juga. Sebagai contoh:

grep -c "tcp" *.txt | awk -v FS=":" -v OFS="\t" '$2>0 { print $2, $1 }' | sort -hr

3

Anda dapat menggunakan yang sederhana grepuntuk menangkap jumlah kejadian secara efektif. Saya akan menggunakan -iopsi untuk memastikan STRING/StrING/stringditangkap dengan benar.

Baris perintah yang memberi nama file:

grep -oci string * | grep -v :0

Baris perintah yang menghapus nama file dan mencetak 0 jika ada file tanpa kejadian:

grep -ochi string *

Bisakah Anda menjelaskan lebih lanjut jawaban Anda dengan menambahkan sedikit deskripsi tentang solusi yang Anda berikan?
abarisone

3

varian rekursif pendek :

find . -type f -exec cat {} + | grep -c 'string'

1
Terima kasih! Hanya solusi Anda yang berfungsi untuk saya (menyimpulkan kecocokan semua file).
Nestor

1

Satu-satunya solusi Grep yang saya uji dengan grep for windows:

grep -ro "pattern to find in files" "Directory to recursively search" | grep -c "pattern to find in files"

Solusi ini akan menghitung semua kemunculan walaupun ada banyak yang terjadi pada satu baris. -rpencarian direktori secara rekursif, -oakan "hanya menampilkan bagian dari garis POLA yang cocok" - inilah yang membagi banyak kejadian pada satu baris dan membuat mencetak grep setiap pertandingan pada baris baru; kemudian pipa hasil yang dipisahkan baris baru ke grep dengan -cuntuk menghitung jumlah kejadian menggunakan pola yang sama.


1

Ini adalah cara alternatif AWK yang lebih cepat daripada grep dalam melakukan ini, yang menangani beberapa kecocokan <url>per baris, dalam kumpulan file XML dalam direktori:

awk '/<url>/{m=gsub("<url>","");total+=m}END{print total}' some_directory/*.xml

Ini bekerja dengan baik dalam kasus di mana beberapa file XML tidak memiliki jeda baris.


0

Oneliner lain menggunakan fungsi baris perintah dasar yang menangani beberapa kejadian per baris.

 cat * |sed s/string/\\\nstring\ /g |grep string |wc -l
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.