Bash: Counting Occurrences of a Character in a String
To count the number of occurrences of a character (letter, digit, symbol) in a string in a bash script, you can use grep and wc:
grep -o `/` <<< $string |wc -l
In this example
- $string - an arbitrary string
/- the delimiter
This symbiosis is very handy if you need to process a list made up of lines of arbitrary length with the same type of delimiter, and you need to cut one or two words out of that list.
If you need to cut out the 5th column in a line, or every fifth field after the delimiter — it’s very easy to do with the cut or awk utilities.
For example, say we have this set of lines combined into a list:
list=`'asd|fgh|jkl
qwe|rty|uio
zxc|vbn|nm<`'
Print the second element of each line:
for f in $list; do echo $f |awk -F`|` '{print $2}';done
or
for f in $list; do echo $f |cut -d `|` -f 2;done
As a result, we get:
fgh
rty
vbn
That’s all fine, but what if the lines have different lengths and we need to print the last element of each line?
For this example I’ll use the following list:
list=`'asd|fgh|jkl|123
qwe|rty|uio|p[]|<?.|456
zxc|vbn|789`'
We need to get the numbers.
In this case there are two tricks:
- Use sed to add one more delimiter to the end of each line and cut out the second-to-last element
- Use bc to add 1 to the count of occurrences and display that element.
First option:
for f in $list;
do
echo $f |cut -d "|" -f $(echo $f |sed 's/$/\|/g' |grep -o "|" |wc -l)
done
In the example:
echo $f |sed 's/$/\|/g' |grep -o "|" |wc -l - does it all at once: adds | to the end of the line and counts the number of occurrences.
Second option:
for f in $list;
do
echo $f |cut -d "|" -f $(bc <<< $(grep -o "|" <<< $f |wc -l)+1);
done
In the example:
-
grep -o "|" <<< $f |wc -l- counts the number of occurrences of the “” delimiter in each line bc <<< $(grep ...)+1- adds one