Посчитайте все вхождения строки во множестве файлов с помощью grep

289

У меня есть куча файлов журналов. Мне нужно выяснить, сколько раз строка встречается во всех файлах.

grep -c string *

возвращается

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

Используя канал, я смог получить только те файлы, которые имеют одно или несколько вхождений:

grep -c string * | grep -v :0

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

Как я могу получить только комбинированный счет? (Если он вернется file4:5, file5:1, file6:2, я хочу вернуться 8.)

Желько Филипин
источник
1
Можете ли вы сказать мне, что делает grep -v: 0? , Я знаю, что это считается для файлов с вхождениями больше 0. Что означает опция -v и: 0 означают? Пожалуйста, дайте мне знать.
Гаутам Хоннавара
@GauthamHonnavara grep: 0 ищет строку, соответствующую строке: 0. -v - это опция для инвертирования этого поиска, поэтому вместо использования grep -v: 0 означает найти все строки, которые не содержат: 0, поэтому строка с файлами file4: 5 и file27: 193 все пройдет, так как они не содержат: 0
penguin359
Вы можете выбрать несколько файлов, используя пробел. grep file1 file2 --options
Днянешвар Харер

Ответы:

288
cat * | grep -c string
Бомбы
источник
9
Это имеет то же ограничение, что он считает несколько вхождений в одной строке только один раз. Я предполагаю, что в этом случае это нормально.
Майкл Харен
@ Michael Haren Да, в строке может быть только одно вхождение.
Желько Филипин
2
Я бы предпочел сделать grep -c string<*так, просто заменив пробел на меньше чем.
JamesM-SiteGen
48
Не обращается к нескольким вхождениям в строке
bluesman
2
Это не работает, если вы хотите искать в подкаталогах тоже, тогда как grep -oи wc -lделает. кошка быстрее в случаях, как оригинальный вопрос, хотя.
Легсайд Гордон
296

Это работает для нескольких вхождений в строке:

grep -o string * | wc -l
Джереми Лавин
источник
2
Это также работает: grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
кодер
2
grep -ioR string * | wc -lэто то, что я использую для поиска без
учета
2
Этот показывает соответствующие файлы, а затем общее количество матчей:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron
28
grep -oh string * | wc -w

будет считать несколько вхождений в строке

Kaofu
источник
24
grep -oh "... my that curry was strong" * >> wc:)
icc97
23

Вместо того, чтобы использовать -c, просто направьте его в wc -l.

grep string * | wc -l

Это перечислит каждое вхождение в одной строке, а затем посчитает количество строк.

Это будет пропускать случаи, когда строка встречается 2+ раза в одной строке.

Майкл Харен
источник
2
Трубопровод к "wc -l" также хорошо работает вместе с "grep -r 'test'". который рекурсивно сканирует все файлы для строки 'test' во всех каталогах ниже текущего.
Стив К
16
cat * | grep -c string

Одно из редких полезных приложений cat.

Йоахим Зауэр
источник
9

Что-то отличное от всех предыдущих ответов:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *
Виджай
источник
приятно видеть подход, не использующий grep, esp, так как мой grep (в windows) не поддерживает опцию -o.
Дэвид Руссел
9

Вы можете добавить -Rк поиску рекурсивно (и избегать использовать cat) и -Iигнорировать двоичные файлы.

grep -RIc string .
azmeuk
источник
7

Обязательное решение AWK:

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

Будьте осторожны, если ваши имена файлов включают в себя «:».

mumrah
источник
5

Решение AWK, которое также обрабатывает имена файлов, включая двоеточия:

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

Имейте в виду, что этот метод все еще не находит несколько вхождений stringв одной строке.

Kreuvf
источник
4

Если вы хотите количество вхождений в файл (например, для строки "tcp"):

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

Пример вывода:

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

Объяснение:

  • grep -RIci NEEDLE . - ищет строку NEEDLE рекурсивно из текущего каталога (по символическим ссылкам), игнорируя двоичные файлы, считая количество вхождений, игнорируя регистр
  • awk ... - эта команда игнорирует файлы с нулевым числом вхождений и форматирует строки
  • sort -hr - сортирует строки в обратном порядке по номерам в первом столбце

Конечно, он работает и с другими командами grep с параметром -c(count). Например:

grep -c "tcp" *.txt | awk -v FS=":" -v OFS="\t" '$2>0 { print $2, $1 }' | sort -hr
Андрей Макуха
источник
3

Вы можете использовать простой, grepчтобы эффективно зафиксировать количество вхождений. Я буду использовать -iопцию, чтобы убедиться,STRING/StrING/string правильно поймают.

Командная строка, которая дает имя файла:

grep -oci string * | grep -v :0

Командная строка, которая удаляет имена файлов и печатает 0, если есть файл без вхождений:

grep -ochi string *
Митул Патель
источник
Не могли бы вы более подробно изложить свой ответ, добавив немного больше описания предлагаемого вами решения?
abarisone
3

короткий рекурсивный вариант:

find . -type f -exec cat {} + | grep -c 'string'
Дмитрий Тарашкевич
источник
1
Спасибо! У меня работало только ваше решение (суммировал совпадения всех файлов).
Нестор
1

Grep единственное решение, которое я тестировал с grep для windows:

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

Это решение будет подсчитывать все вхождения, даже если их несколько в одной строке. -rрекурсивно ищет в каталоге, -o«покажет только часть строки, соответствующую PATTERN» - это то, что разбивает несколько вхождений на одну строку и заставляет grep печатать каждое совпадение на новой строке; затем передайте эти результаты с разделением на новую строку обратно в grep, -cчтобы подсчитать количество вхождений, используя тот же шаблон.

Quantic
источник
1

Вот более быстрый, чем grep AWK альтернативный способ сделать это, который обрабатывает несколько совпадений <url>на строку в коллекции файлов XML в каталоге:

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

Это хорошо работает в тех случаях, когда некоторые XML-файлы не имеют разрывов строк.

Excalibur
источник
0

Другой oneliner, использующий основные функции командной строки, обрабатывающий несколько вхождений на строку.

 cat * |sed s/string/\\\nstring\ /g |grep string |wc -l
NTwoO
источник