You can group an optional dot with 2-4 characters that should follow it: (\.[az]{2,4}) . However, you will either have no or up to two of these groups of characters with a dot + alphabet (\.[az]{2,4}){0,2} .
The required end with the [az] , you can check with a positive lookbehind (?<=[az]) , indicating this as a complete regex:
^[a-z0-9]+(\.[az]{2,4}){0,2}(?<=[az])$
This will work in Perl and PHP regexes (PCRE), but not in JavaScript, because it does not support lookbehind. In this particular case, you can circumvent this limitation.
If there is at least one point, there is already a guarantee that it will end on [az] , because this test is in the group in which the point is located. If there is no point, you need to force press [az] at the end. To do this, you can turn the quantifier of one or more ( + ) into zero or more ( * ) and force the end to be [az] when there are no "point groups". When there are groups of points, you can save the same pattern, but now with at least one required point.
^([a-z0-9]*[az]|[a-z0-9](+\.[az]{2,4}){1,2})$
source share