I've taught a few "intro to regex" classes and have settled on a very simple explanation that seems to work even with fairly non-technical audiences. In short:

1) Regular expressions and "regex" are different things. Regex is a superset of regular expressions. But if you can understand regular expressions you can understand a huge number of regexes and have the tools to understand the rest of the syntax that the system uses.

2) There are many many many regular expression and regex dialects and engines. It's useful to learn the dialect you are trying to use.

3) Originally, regular expressions were used to describe a generator of strings. It can be helpful to approach writing regexes from this standpoint. It's not about what it matches, but what strings the regex can produce. I've had many students go from bewildered incomprehension to immediate eureka when I describe this.

4) There are only three rules that the beginning regex user has to know:

i) Concatenation - you can make a bigger generator by combining one generator after the other. For example: the regex 'a' and the regex 'b' can be concatenated into 'ab' and produces only the string 'ab'.

ii) Alternation - you can specify one character or another using the pipe character in most dialects '|'. For example the regex 'a|b' produces either the string 'a' or 'b'.

iii) Repetition - the character ' * ' is a postfix operator that means that the character that preceeds it can be repeated zero to an infinite number of times. For example: 'a* ' produces the empty string, 'a', 'aa', 'aaa' and so on.

5) By combining these (i.e. using concatenation) and the grouping operators '(' ')' you can write a regex for almost anything.

6) Nearly all of the other character you see in regexes that don't make sense are simply syntactic sugar that make it easier and shorter to write common expressions in a more compact form. Examples:

Writing lots of alternations of single characters (called character classes)
- 'a|b|c|d|e|f' can be written as [a-f]
- an expression that is the alternation of every character except the newline character can be written as '.'
There's a whole host of these kinds of things.

Writing lots of different kinds of repetitions introduces lots of new operators
- 'aa* ' can be written as 'a+' where '+' means 'repeat the previous character 1 or more times
- 'a?' means 'repeat the previous character 0 or one times'
- 'a{1,5}' means 'repeat the previous character 1 to 5 times'
There's also an entire table of these things.

After that it's mostly practice and referring to the description of the operators for the dialect you are using.

I usually cover capture groupings (e.g. \1, \2, \3 or $1, $2, $3) later on if necessary as it requires people to have a good handle on the particulars of their languages way of handling those things. At this time I'll also over the '(?:.)' non-capture group operator if their dialect allows.

About as frequently I'll have to introduce '^' and '$' and begin and end string operators and also deconflict it from '[^.]'.

All the crazy-ass back/forward reference stuff I usually leave out as people almost never need or come across those except in pretty rare instances. In those cases they usually have enough regex under their belt that it's just another topic to pick up.

This doesn't get anybody to pro-wizard level and there's always edge cases and weird Perl-golf stuff that's out there, but it'll get most people to generally functional inside of a day or two and I'll just make myself available to spot answer questions or remind them where they forgot something.