CLI AI

Посчитать вхождения в логе: grep -c — не тот ответ

2026-08-11

grep -c ERROR app.log считает строки, в которых встретилось слово; grep -o ERROR app.log | wc -l считает, сколько раз слово встретилось на самом деле. На одном и том же файле это 3 и 4, а разница — единственная строка с двумя ошибками. Какое число нужно вам, зависит от вопроса, который вы имели в виду.

1. Сколько строк содержит слово

clai
$ clai сколько строк в app.log содержат ERROR→ grep -c ERROR app.log3

-c считает строки с совпадением, а не совпадения. Строка, где ERROR встретился дважды, всё равно считается за одну.

2. Сколько раз встречается слово

clai
$ clai сколько раз встречается ERROR в app.log→ grep -o ERROR app.log | wc -l4

3 против 4 на том же самом файле. -o печатает каждое совпадение отдельной строкой, и только после этого wc -l считает вхождения. Лишнее — та самая строка с двумя ошибками.

3. Без учёта регистра

clai
$ clai посчитай строки с error в любом регистре→ grep -ic error app.log4

-i подобрал четвёртую строку — ту, где слово написано строчными. В логе, куда пишут несколько сервисов, регистр никто не гарантирует.

4. Топ сообщений об ошибках

clai
$ clai покажи, какие ошибки встречаются чаще всего→ grep -o 'ERROR [a-z ]*' app.log | sed 's/ *$//' | sort | uniq -c | sort -rn      2 ERROR timeout connecting to db      1 ERROR retry failed      1 ERROR permission denied

Обычно ради этого всё и затевается. -o вытаскивает текст ошибки, sed убирает хвостовые пробелы, uniq -c считает, а второй sort -rn поднимает частые наверх.

5. Распределение по часам

clai
$ clai покажи, в какие часы были ошибки→ grep ERROR app.log | cut -c12-13 | sort | uniq -c      1 09      1 10      1 11

cut -c12-13 вырезает час из отметки времени вида 2026-08-10 09:12:03. Позиции зависят от формата вашего лога — посмотрите на одну строку и пересчитайте символы, прежде чем копировать.

6. Сразу по нескольким файлам

clai
$ clai посчитай ошибки в каждом файле логов→ grep -c ERROR *.logapp.log:3app2.log:3

Когда файлов больше одного, grep печатает имя и счётчик через двоеточие. Чтобы отранжировать: grep -c ERROR *.log | sort -t: -k2 -rn.

Gotchas

  • grep -c не считает вхождения. Проверено на одном файле: -c говорит 3, -o | wc -l говорит 4. Если строка совпала дважды, -c этого не видит. Решите, какой вопрос вы задаёте: «сколько строк» или «сколько раз».
  • grep -o без совпадений печатает пустоту и выходит с кодом 1. В конвейере с wc -l это выглядит как честный ноль, но статус ненулевой, и скрипт с set -e умрёт ровно здесь.
  • Позиции в cut -c привязаны к формату лога. Стоит логгеру добавить миллисекунды или имя хоста в начало строки, и разбивка по часам молча посчитает не те символы. Для нестабильных форматов берите поля: awk '{print $2}'.

Related questions

Как считать слова целиком, а не подстроки? grep -wo error — -w требует границ слова, иначе в счёт попадут errors и errorlog.

Как считать в сжатых логах? zgrep -c ERROR app.log.1.gz работает как grep и не распаковывает файл на диск.

Как посчитать разные значения? Добавьте sort -u перед подсчётом: grep -o 'ERROR [a-z ]*' app.log | sort -u | wc -l покажет число различных сообщений, а не их общее количество.

See also

CliAI превращает «сколько раз» и «сколько строк» в две разные команды и показывает, какую именно выбрал. Поставить одной строкой.