The reason your regex doesn't always work can be either (or all) of the following:

- some of the bad words contain characters special to regex, like { or } or \ etc

- you didn't use regex quotes around the pattern, ie /badword1|badword2/i. Omitting quotes can fail if the first badword starts with "m" or if the said bad word contains capital letters (regex is case-sensitive unless you tell it otherwise, with the "i" modifier).

If I had relatively few bad words to watch for, I'd probably do it like this:
on @$*:text:$($+(/\Q,$replacecs(%badwords,\E,\E\\E\Q,$chr(44),\E|\Q),\E/iS)):#:{
  ban -k # $nick 2 Don't swear

This is similar to your regex way but also takes into consideration the things I said above. Note the %badwords variable; this should contain all bad words (or even phrases), separated by a comma. You'd set that variable once with
/set %badwords word1,word2,some phrase1,word3

If I had many words (more than 50), I'd use the technique described here. It's the fastest possible way of checking a line of text against many bad words. One thing only: $hmatch(swear_words,$strip($1-)) in that tutorial can be replaced by $hfind(swear_words,$strip($1-),1,[color:red]W)[/color] (capital W). Both work (at least for now), but $hmatch() is obsolete. The new version is $hfind(), so you'd better get used to using this instead.

/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com