简体   繁体   中英

Count the number of occurrences of a pattern in a string (with bash builtins only)

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 ?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM