I need to count the number of occurrences of a char in a string using Bash.

In the following example, when the char is (for example) t, it echos the correct number of occurrences of t in var, but when the character is comma or semicolon, it prints out zero:

var = "text,text,text,text" 
num = `expr match $var [,]`
echo "$num"

I would use the following awk command:

awk -F"${char}" '{print NF-1}' <<< "${string}"

I'm splitting the string by $char and print the number of resulting fields minus 1.

If your shell does not support the <<< operator, use echo:

echo "${string}" | awk -F"${char}" '{print NF-1}'
  • what if var is a file with text. how can the above be altered for this? – HattrickNZ Sep 11 '14 at 3:17
  • 4
    @HattrickNZ Then use: $(grep -o "$needle" < filename | wc -l) – hek2mgl Sep 11 '14 at 8:26
  • 13
    @Amir What do you expect? – hek2mgl Sep 12 '14 at 9:02
  • 2
    You can skip the wc -l, just use grep -c, it works on both bsd grep and linux grep. – andsens Aug 5 '16 at 11:54
  • 7
    @andsens grep -c will only output the number of matching lines. It does not count multiple matches per line. – hek2mgl Aug 5 '16 at 12:19

you can for example remove all other chars and count the whats remains, like:

echo "$res"
echo "${#res}"

will print



tr -dc ',' <<<"$var" | awk '{ print length; }'


tr -dc ',' <<<"$var" | wc -c    #works, but i don't like wc.. ;)


awk -F, '{print NF-1}' <<<"$var"


grep -o ',' <<<"$var" | grep -c .


perl -nle 'print s/,//g' <<<"$var"
  • 1
    some more trick here like y="${x//[^s|S]}"; echo "${#y}" – Aquarius Power Jun 13 '14 at 0:11
  • 4
    use the first one, should always avoid resorting to spawning another process to do work like this, it can severely impact performance when using with large iteration loops. As a rule external process execution should be a last resort when using iterating or repeating operations. – osirisgothra Jun 21 '14 at 10:17
  • Why don't you like wc? It golfs! – Ciro Santilli 新疆改造中心996ICU六四事件 Nov 19 '15 at 23:16
  • 1
    @CiroSantilli六四事件法轮功包卓轩because for example echo -n some line | wc -l – jm666 Nov 20 '15 at 2:04
  • Code block 4 is the best in my opinion. We need to make it easier to get to: tr -dc ',' <<<"$var" | wc -c – bgStack15 Feb 26 '16 at 14:57

You can do it by combining tr and wc commands. For example, to count e in the string referee

echo "referee" | tr -cd 'e' | wc -c



Explanations: Command tr -cd 'e' removes all characters other than 'e', and Command wc -c counts the remaining characters.

Multiple lines of input are also good for this solution, like command cat mytext.txt | tr -cd 'e' | wc -c can counts e in the file mytext.txt, even thought the file may contain many lines.

  • 3
    Your solution seems to be the cleanest and easiest to remember, thanks! – jirislav Feb 12 '18 at 13:15
  • This is great. Thank you! – Kodie Grantham Jul 18 '18 at 17:32

Building on everyone's great answers and comments, this is the shortest and sweetest version:

grep -o "$needle" <<< "$haystack" | wc -l


awk works well if you your server has it

num=$(echo "${var}" | awk -F, '{print NF-1}')
echo "${num}"
  • Just as a note: awk -F, looks for a ,. You can do the following: awk -F"${your_char}" – Emixam23 Mar 19 at 14:49

I Would suggest the following:

var="any given string"
(( G = N - G ))
echo "$G"

No call to any other program

protected by Inian Jan 24 at 5:25


Would you like to answer one of these unanswered questions instead?
