A very common pattern for novices that is considered "incorrect" is
cat "$filename" | grep "$some_string"
because you don't need a pipe | when you use:
grep "$some_string" "$filename"
Slightly more advanced and performant is to use some of the switches in the GNU version of grep:
man grep
-c, --count
Suppress normal output; instead print a count of matching
lines for each input file.
That immediately and natively gives the the same count of matching lines as piping your grep "$some_string"
output to | wc -l
When you only want to know if a string occurs 20 times or more in the file: you can stop processing the file contents after grep
has found 20 matching lines which is really useful in a file many 100's of GB's or more that may contain a great many occurrences of "$some_string"
.
man grep
-m NUM, --max-count=NUM
Stop reading a file after NUM matching lines. If NUM is
zero, grep stops right away without reading input. A NUM
of -1 is treated as infinity and grep does not stop; this
is the default. If the input is standard input from a
regular file, and NUM matching lines are output, grep
ensures that the standard input is positioned to just
after the last matching line before exiting, regardless of
the presence of trailing context lines. This enables a
calling process to resume a search. When grep stops after
NUM matching lines, it outputs any trailing context lines.
When the -c or --count option is also used, grep does not
output a count greater than NUM.
And that then comes together as (untested and unrefined)
/bin/bash
some_string="sa_mg"
filename="mongod.log*"
count=$(grep -c -m 20 "$some_string" "$filename")
if [ "$count" -ge "20" ] ; then
echo "found 20 or more occurrences"
fi
Linting you shell script code with for example https://www.shellcheck.net/ (or the locally installed linter) will help you write "better" scripts.