Grep: count number of matches per line

I'm trying to get the number of matches (in this case occurrences of { or }) in each line of a .tex file.

I know that the -o flag returns only the match, but it returns each match on a new line, even combined with the -n flag. I don't know of anything I could pipe this through to count the repeats. The -c flag only returns the total number of matches in the entire file - maybe I could pipe one line at a time to grep?


grep -o -n '[{}]' <filename> | cut -d : -f 1 | uniq -c

The output will be something like:

3 1
1 2

Meaning 3 occurrences in the first line and 1 in the second.

Taken from https://stackoverflow.com/a/15366097/3378354 .


After reading various solutions, I think this is the easiest approach to the problem:

while read i; do echo $i |grep -o "matchingString"| wc -l;  done < input.txt

Is using grep a requirement?  Here’s an alternative:

sed 's/[^{}]//g' your_file | awk '{print NR, length }'

The sed strips out all characters other than { and } (i.e., leaving only { and } characters), and then the awk counts the characters on each line (which are just the { and } characters).  To suppress lines with no matches,

sed 's/[^{}]//g' your_file | awk '/./ {print NR, length }'

Note that my solution assumes (requires) that the strings you are looking for are single characters.  Moebius’s answer is more easily adapted to multi-character strings.  Also, neither of our answers excludes quoted or escaped occurrences of the characters/strings of interest; e.g.,

{ "nullfunc() {}" }

would be considered to contain four brace characters.


AWK can do this by itself, piping multiple processes is not necessary.

awk '{print NR " " gsub(/[{}]/, "")}'

Example:

$ printf 'test{}\n abc\n }{{}\n xyz}' | awk  '{print NR " " gsub(/[{}]/, "")}'
1 2
2 0
3 4
4 1

The grep count option -c is a con job. It does not return the total count you expect (it is actually just a line count, not a match count).

$ printf 'test{}\n abc\n }{{}\n xyz}' | grep -con "[{}]"
3

awk can get a total count like this:

$ printf 'test{}\n abc\n }{{}\n xyz}' | awk -F"[{}]" '{c+=NF-1} END {print c}'
7