17612.4.9.1.8 cannot be considered as an integer. Not even as a number: too many dots. If you want to compare dot-separated versions you must do this one field at a time, starting from the major version number.
One option is to store the fields in an array:
$ m=(${monterey//./ })
$ echo ${m[0]}
17612
$ echo ${#m[@]}
5
m=(${monterey//./ }) replaces all dots in $monterey by spaces and stores the result in array m, one space-separated word per cell. ${#m[@]} expands as the size of the array. So, something like the following should do what you want:
m=(${monterey//./ })
v=(${version//./ })
(( n = ${#v[@]} < ${#m[@]} ? ${#m[@]} : ${#v[@]} ))
for (( i=0; i < n; i++ )); do
if (( ${v[i]:-0} < ${m[i]:-0} )); then
echo "Needs update"
break
elif (( ${v[i]:-0} > ${m[i]:-0} )); then
echo "Up to date"
break
fi
done
exit 0
(( n = ${#v[@]} < ${#m[@]} ? ${#m[@]} : ${#v[@]} )) stores the largest array size in variable n. ${v[i]:-0} expands as v[i] if it is set and not the empty string, else as 0.
But if you can use sort, instead of plain bash, you can also use:
l=$(printf '%s\n%s\n' "$monterey" "$version" | sort -nt. | tail -n1)
if [[ $version = $l ]]; then
echo "Up to date"
else
echo "Needs update"
fi
exit 0
The first command sorts the two versions numerically (-n), using . as separator (-t.), keeps only the last (tail -n1), that is, the largest, and stores it in variable l. Note that this could not work as you would like if you can have trailing 0 fields: 1.2.0.0 will be considered as larger than 1.2.0 or 1.2.
As mentioned by @markp-fuso, if your sort utility supports it (it is a non-POSIX feature found, for instance, in the GNU coreutils sort), you can also use its -V option that does exactly what you want:
l=$(printf '%s\n%s\n' "$monterey" "$version" | sort -V | tail -n1)