Count the number of occurrences of a substring in a string
With perl
:
printf '%s' "$SUB_STRING" |
perl -l -0777 -ne '
BEGIN{$sub = <STDIN>}
@matches = m/\Q$sub\E/g;
print scalar @matches' <(printf '%s' "$STRING")
With bash
alone, you could always do something like:
s=${STRING//"$SUB_STRING"}
echo "$(((${#STRING} - ${#s}) / ${#SUB_STRING}))"
That is $s
contains $STRING
with all occurrences of $SUB_STRING
within it removed. We find out the number of $SUB_STRING
s that were removed by computing the difference in number of characters in between $STRING
and $s
and dividing by the length of $SUB_STRING
itself.
POSIXly, you could do something like:
s=$STRING count=0
until
t=${s#*"$SUB_STRING"}
[ "$t" = "$s" ]
do
count=$((count + 1))
s=$t
done
echo "$count"
Using string processing functions we could do it with Perl as follows :
printf '%s\n' "$STRING" |
perl -nse '
$_ .= join "", <>;
$k++ while ++($p = index($_, $s, $p));
print $k, "\n" ;
' -- -s="$SUB_STRING"
Explanation:
° load up the whole string in $_
° index function will return the position of a substring in a string OTW returns -1
° progressively match the substring and use the position found as the starting position for the next search.
° all this while increment the counter $k depicting substring found.
Some other methods are listed below:
Slurp the string and use regex.
printf '%s\n' "$STRING" |
perl -slp -0777e '
$_ = () = /$s/g;
' -- -s="$s"
° Slurp string into the $_ variable.
° pass the substring from the command line to perl using the -s option.
° now perform a match on $_ and in a list context gets you the matches which are then take in scalar context to get the number of matches.
° the -p option shall autoprints what's in $_.
Method using the sed tool :
esc_s=$(printf '%s\n' "$SUB_STRING" |\
sed -e 's:[][\/.^$*]:\\&:g' -e 'H;1h;$!d;g;s/\n/\\n/g')
printf '%s\n' "$STRING" |
sed -ne '
$!{N;s/^/\n/;D;}
/'"$esc_s"'/{
x;p;x
s///;s/^/\n/;D
}
' | wc -l
° As a preparatory step, we go ahead and escape all characters acting as meta characters to the left hand side of s/// statement in the substring which if not done will cause the sed to crash.
° Now we slurp the whole of string into the pattern space.
° then we keep printing an empty line, the hold space is a good candidate, and take away the substring from the pattern space.
° rinse... lather... repeat so long as substring is present.
° the empty lines are then piped to the wc tool which will get us the count of lines = number of times substring was found.
This is shell version:
e=$STRING N=0
while
e=$(expr " $e" : " \(.*\)$SUB_STRING")
case $e in "" ) break ;; esac
do
N=$(expr "$N" + 1)
done
echo "$N"
You can use Python like in this question
python -c 'print "abcdabcva".count("ab")'
Or if you are working with shell variables:
python -c 'print("""'"$STRING"'""".count("""'"$SUB_STRING"'"""))'
In your case:
python -c 'print """0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no""".count("""Bluetooth
Soft blocked: no
Hard blocked: no""")'