Reputation: 8205
I have a string which looks like this:
STRING="$PATTERN_some-stuff_$PATTERN_some-other_stuff"
I would like to count the number of occurences of $PATTERN
in it, only with Bash builtin commands.
The more straightforward way of doing this I have found so far is to extract from the string only the strings that match $PATTERN
, and then to count how many occurrences of $PATTERN
there are in the newly created string, proceeding this way:
expr length "${STRING//[^$PATTERN]}" / ${#PATTERN}
But it only works if $PATTERN
is a single character. I tried to use the syntax ${STRING//!(PATTERN)}"
, which would, if I understand well Bash manual, only match $PATTERN
at the exclusion of the rest of $STRING
, but it actually outputs nothing. So, where am I wrong ?
Upvotes: 3
Views: 5125
Reputation: 246807
If you're a bit flexible about builtins only, this is a perfect situation for grep -o
:
$ STRING='$PATTERN_some-stuff_$PATTERN_some-other_stuff'
$ grep -o '$PATTERN' <<< "$STRING" | wc -l
2
Upvotes: 6
Reputation: 23364
One option is to replace all instances of PATTERN in STRING, subtract the length of this shortened string from the length of STRING, and then divide this by length of PATTERN. And by the way, you have flouted your bash built-in requirement by using expr
. expr
is a command(at least on my Ubuntu server)
$ declare -- PATTERN="abracadabra"
$ declare -- STRING="${PATTERN}_some-stuff_${PATTERN}_some-other_stuff"
$ echo $STRING
abracadabra_some-stuff_abracadabra_some-other_stuff
$ temp=${STRING//$PATTERN}
$ string_length_without_patterns=${#temp}
$ total_pattern_length=$((${#STRING} - $string_length_without_patterns))
$ number_of_patterns=$(($total_pattern_length/${#PATTERN}))
$ echo $number_of_patterns
2
Upvotes: 2