If you restrict yourself to "real" regular expressions (avoid Perl extensions and such), they express regular languages[1], which do compose very well, and can be compiled into finite state machines.
Regular languages are closed not only under concatenation and Kleene star, but also:
- union
- intersection
- complement
- reverse
and more.[1]Real FST libraries like HFST or OpenFST let you compile and compose regular expressions this way. It's too most "standard" regex libraries stop at "re.compile" and never implement concat/intersect/complement/reverse/union.
-----
For the readability issue, give rx[2] a go – you can turn plain regexes into rx syntax with xr[3] :)
[1] https://en.wikipedia.org/wiki/Regular_language#Closure_prope...