Policz wszystkie wystąpienia ciągu w wielu plikach z grep

289

Mam kilka plików dziennika. Muszę dowiedzieć się, ile razy łańcuch występuje we wszystkich plikach.

grep -c string *

zwroty

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

Za pomocą potoku udało mi się uzyskać tylko pliki, które mają jedno lub więcej wystąpień:

grep -c string * | grep -v :0

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

Jak mogę uzyskać tylko łączną liczbę? (Jeśli to wróci file4:5, file5:1, file6:2, chcę odzyskać 8.)

Željko Filipin
źródło
1
Czy możesz mi powiedzieć, co robi grep -v: 0? . Wiem, że to się liczy dla plików, których wystąpienie jest większe niż 0. Co oznacza opcja -v i: 0? Daj mi znać.
Gautham Honnavara,
@GauthamHonnavara grep: 0 szuka linii pasującej do ciągu: 0. -v jest opcją odwrócenia tego wyszukiwania, więc zamiast grep -v: 0 oznacza znajdowanie wszystkich linii, które nie zawierają: 0, więc linia z plikiem 4: 5 i plikiem 27: 193 przejdzie wszystkie, ponieważ nie zawierają: 0
penguin359
Możesz wybrać wiele plików za pomocą spacji. grep file1 file2 --options
Dnyaneshwar Harer

Odpowiedzi:

288
cat * | grep -c string
Bombe
źródło
9
Ma to to samo ograniczenie, że zlicza wiele wystąpień w jednym wierszu tylko raz. Zgaduję jednak, że takie zachowanie jest w tym przypadku OK.
Michael Haren,
@Michael Haren Tak, może występować tylko jedno wystąpienie ciągu w linii.
Željko Filipin
2
Wolę to zrobić, grep -c string<*po prostu zastępując przestrzeń na mniej niż.
JamesM-SiteGen
48
Nie odnosi się do wielu wystąpień na linii
bluesman
2
To nie działa, jeśli chcesz przeszukiwać również podkatalogi, grep -oa jednocześnie wc -ldziała. kot jest szybszy w przypadkach takich jak oryginalne pytanie.
Leagsaidh Gordon
296

Działa to dla wielu wystąpień w wierszu:

grep -o string * | wc -l
Jeremy Lavine
źródło
2
Działa to również: grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
programista
2
grep -ioR string * | wc -lto jest to, czego używam do wyszukiwania bez rozróżniania wielkości liter, rekurencyjnego wyszukiwania tylko z dopasowaniem
LeonardChallis
2
Ten pokazuje odpowiednie pliki, a następnie całkowitą liczbę dopasowań:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron
28
grep -oh string * | wc -w

policzy wiele wystąpień w linii

Kaofu
źródło
24
grep -oh "... my that curry was strong" * >> wc:)
icc97
23

Zamiast używać -c, po prostu potokuj go do wc -l.

grep string * | wc -l

Spowoduje to wyświetlenie każdego wystąpienia w jednej linii, a następnie policzy liczbę linii.

Pominie to jednak przypadki, w których ciąg występuje ponad 2 razy w jednej linii.

Michael Haren
źródło
2
Piping do „wc -l” działa również dobrze z „grep -r 'test”. który skanuje rekurencyjnie wszystkie pliki w poszukiwaniu ciągu „test” we wszystkich katalogach poniżej bieżącego.
stevek,
16
cat * | grep -c string

Jedna z rzadkich przydatnych aplikacji cat.

Joachim Sauer
źródło
9

Coś innego niż wszystkie poprzednie odpowiedzi:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *
Vijay
źródło
miło widzieć podejście bez użycia grep, szczególnie, że mój grep (w systemie Windows) nie obsługuje opcji -o.
David Roussel,
9

Możesz dodawać -Rdo wyszukiwania rekurencyjnie (i unikać używania cat) i -Iignorować pliki binarne.

grep -RIc string .
azmeuk
źródło
7

Obowiązkowe rozwiązanie AWK:

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

Uważaj, jeśli twoje nazwy plików zawierają „:”.

mumrah
źródło
5

Rozwiązanie AWK, które obsługuje również nazwy plików, w tym dwukropki:

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

Należy pamiętać, że ta metoda nadal nie wykrywa wielu wystąpień stringtej samej linii.

Kreuvf
źródło
4

Jeśli chcesz liczbę wystąpień na plik (przykład dla ciągu „tcp”):

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

Przykładowe dane wyjściowe:

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

Wyjaśnienie:

  • grep -RIci NEEDLE . - wyszukuje rekurencyjnie ciąg NEEDLE z bieżącego katalogu (następujące dowiązania symboliczne), ignorując pliki binarne, licząc liczbę wystąpień, ignorując wielkość liter
  • awk ... - to polecenie ignoruje pliki o zerowym wystąpieniu i formatuje linie
  • sort -hr - sortuje wiersze w odwrotnej kolejności według liczb w pierwszej kolumnie

Oczywiście działa również z innymi poleceniami grep z opcją -c(liczba). Na przykład:

grep -c "tcp" *.txt | awk -v FS=":" -v OFS="\t" '$2>0 { print $2, $1 }' | sort -hr
Andriy Makukha
źródło
3

Możesz użyć prostego, grepaby skutecznie uchwycić liczbę wystąpień. Wykorzystam tę -iopcję, aby upewnić STRING/StrING/stringsię, że zostaniesz poprawnie przechwycony.

Wiersz poleceń podający nazwę plików:

grep -oci string * | grep -v :0

Wiersz polecenia, który usuwa nazwy plików i drukuje 0, jeśli istnieje plik bez wystąpień:

grep -ochi string *
Mitul Patel
źródło
Czy mógłby Pan uściślić swoją odpowiedź, dodając nieco więcej opisu oferowanego rozwiązania?
abarisone
3

krótki wariant rekurencyjny :

find . -type f -exec cat {} + | grep -c 'string'
Dmitrij Tarashkevich
źródło
1
Dziękuję Ci! Tylko twoje rozwiązanie działało dla mnie (zsumowane dopasowania wszystkich plików).
Nestor,
1

Tylko rozwiązanie Grep, które testowałem z grep dla Windows:

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

To rozwiązanie policzy wszystkie wystąpienia, nawet jeśli jest ich wiele w jednej linii. -rrekurencyjnie przeszukuje katalog, -o„pokaże tylko część wiersza pasującego WZORZEC” - to właśnie dzieli wiele wystąpień w jednym wierszu i powoduje, że grep drukuje każde dopasowanie w nowym wierszu; następnie potokuj wyniki rozdzielone znakiem nowej linii z powrotem do grep, -caby policzyć liczbę wystąpień przy użyciu tego samego wzorca.

Kwantowy
źródło
1

Oto szybszy niż grep alternatywny sposób AWK, który obsługuje wiele dopasowań w <url>wierszu, w kolekcji plików XML w katalogu:

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

Działa to dobrze w przypadkach, gdy niektóre pliki XML nie mają podziałów linii.

Excalibur
źródło
0

Kolejny oneliner korzystający z podstawowych funkcji wiersza poleceń obsługujących wiele wystąpień w wierszu.

 cat * |sed s/string/\\\nstring\ /g |grep string |wc -l
NTwoO
źródło