You start out with a basic string comparison. Very easy, but also not that powerful.
Next, it may have occured to you, that you need case insesitive comparisions, so that "greek" and "GreeK" compare equal. This is a bit more powerful.
One day you notice small differences in spelling should not prevent 2 words from comparing equal: i.e. "organize" and "organise" should compare equal. You sit down and write some code that does this and you're happy.
Until you abstract a bit more and realize that you sometimes want all words that end in "ize" to compare equal with their brothers in british spelling. Or, repetitions of some strings a certain amount of times. And, of course, you need to combina all that.
And so on. Finally, you most likely end up with some notation where not every character stands for itself. Nothing else is a regexp. One can see it as description of a set of strings.
And then, it is fairly easy and comes down to the following 3 basic principles:
You have basic regexps: chars that stand for themselves, character classes, handy and not so handy abbreviations for character classes like \d or \p{Lu} for uppercase letters.
And then, you have some possibilities to combine them: if r1 and r2 are regexps, then so are r1r2 r1|r2 (r1).
Last, but not least the repetition modifiers: r? r* r+ r{n,m}
This is most you need to know. Anything else you can lookup when you need it.