Количество вхождений шаблона в файл (даже в одной строке)
при поиске количества вхождений строки в файле я обычно использую:
grep pattern file | wc -l
однако это находит только одно вхождение на строку из-за того, как работает grep. Как я могу искать количество раз, когда строка появляется в файле, независимо от того, находятся ли они в одной или разных строках?
кроме того, что, если я ищу шаблон регулярного выражения, а не простую строку? Как я могу их сосчитать или, что еще лучше, распечатать каждый матч на новом линия?
5 ответов
подсчитать все вхождения, используйте -o
. Попробуйте это:
echo afoobarfoobar | grep -o foo | wc -l
и man grep
конечно (:
обновление
некоторые предлагают использовать просто grep -co foo
вместо grep -o foo | wc -l
.
нет.
этот ярлык не будет работать во всех случаях. Man page говорит:
-c print a count of matching lines
разница в этих подходах иллюстрируются ниже:
1.
$ echo afoobarfoobar | grep -oc foo
1
как только матч будет найден в линия (a{foo}barfoobar
), то поиск прекращается. Была проверена только одна строка, и она совпала, поэтому вывод 1
. На самом деле -o
игнорируется здесь, и вы можете просто использовать .
2.
$ echo afoobarfoobar | grep -o foo
foo
foo
$ echo afoobarfoobar | grep -o foo | wc -l
2
в строке (a{foo}bar{foo}bar
), потому что мы явно попросили найти каждый возникновения (-o
). Каждое событие печатается отдельной строкой, и wc -l
просто подсчитывает количество строк в выводе.
попробуйте это:
grep "string to search for" FileNameToSearch | cut -d ":" -f 4 | sort -n | uniq -c
пример:
grep "SMTP connect from unknown" maillog | cut -d ":" -f 4 | sort -n | uniq -c
6 SMTP connect from unknown [188.190.118.90]
54 SMTP connect from unknown [62.193.131.114]
3 SMTP connect from unknown [91.222.51.253]
запоздалый пост:
Использовать шаблон поиска regex как запись сепаратор (РС) в awk
Это позволяет вашему регулярному выражению span \n
- разделенные линии (если вам это нужно).
printf 'X \n moo X\n XX\n' |
awk -vRS='X[^X]*X' 'END{print (NR<2?0:NR-1)}'
Ripgrep, который является быстрой альтернативой grep, только что представил --count-matches
флаг, который позволяет считать каждого матч в версии 0.9 (я, используя приведенный выше пример, чтобы оставаться последовательным):
> echo afoobarfoobar | rg --count foo
1
> echo afoobarfoobar | rg --count-matches foo
2
как спросил OP, ripgrep также позволяет использовать шаблон регулярных выражений (--regexp <PATTERN>
).
Также он может печатать каждый (строка) матч на отдельной строке:
> echo -e "line1foo\nline2afoobarfoobar" | rg foo
line1foo
line2afoobarfoobar
взломать функцию цвета grep и подсчитать, сколько цветных тегов он распечатывает:
echo -e "a\nb b b\nc\ndef\nb e brb\nr" \
| GREP_COLOR="033" grep --color=always b \
| perl -e 'undef $/; $_=<>; s/\n//g; s/\x1b\x5b\x30\x33\x33/\n/g; print $_' \
| wc -l