Your script will be somewhat slower than it needs to be. It's doing a scripted comparison of the message against the list of allowed characters. It would be much faster to let that comparison loop happen inside the $regex identifier.

https://en.wikichip.org/wiki/mirc/regex

The simplest verify against the allowed list would look something like:

//echo -a $regex(string,/[^abcdef]/u)

This looks at the string and checks to see if it can find a character that is NOT on the list. As soon as it does, $regex returns '1' indicating the number it found. If you're interested in how many bad characters there are, you can change the /u to /ug and it will return the number of matches instead of 1. But this will take slightly longer since it doesn't return as soon as it finds something not on the list.

With this method, you can also avoid the $remove of the spaces by simply having spaces be as part of your list.

If you want to allow color/control codes without needing to put them into %allowed you can add the "S" flag by changing /u to /uS. The /u identifier is not needed until you start putting codepoints outside the normal 7-bit text range, but it's harmless to leave it there. Without the /u flag, if it encounters a codepoint above 127, it instead sees the individual bytes making up the UTF8 encoding, instead of seeing the codepoint character.

Inside the [list] you need to make sure that any chars with special meaning have been 'escaped' by preceding them with a \backslash. For example, if you have a hyphen in the list that's not in the first/last position, it behaves like a range, so [^a-z] means the range 'a' THROUGH 'z' not the 2 letters and the hyphen. The ^ as the 1st character means 'not the following characters, but anywhere else it means the literal carat.

So, just to be safe, you should preced these characters with a backslash: []-^\

Just to be clear, there are other characters having special meaning in other places in a regex pattern, but not inside the [list].

//var %string foo bar , %allowed !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ | var -s %pattern $+( /[^, $replacecs(%allowed,\,\\,[,\[,],\],-,\-,^,\^) ,]/u) | echo -a $regex(%string,%pattern)

Note how this example returns a '1' because the string contains a space which I didn't put in the list. But as soon as you add the space anywhere inside the %allowed list, then it reports 0 (zero characters not in the list).

If you change it so you do not $replacex "-" with "\-" then you can have the variable be much shorter, because you can have ranges defined by the characters sandwiching the hyphen. Instead of listing the entire alphabet, you can just have A-Z. If you want to avoid listing the A-Z a-z alphabet twice, you can add the 'i' flag, changing /u to /ui. The /i flag seems to only see case-insensitive within the A-Z and a-z ranges, and not among the accented characters above codepoint 127.

While only those 5 characters have special meaning in a regex [list], there are other characters that you'll have trouble with if you try to use them literally inside the $regex() identifier. But only because they have special meaning to mIRC, such as commas, parenthesis, dollars, etc. But by parking them in a %variable like you did, that also avoids a lot of problems.