Whoever accompanies me here in SOpt knows that I do not do much features other than those provided for regular languages . / p>
The response provided by @nunks.lol uses negative lookbehind , which is not regular in the mathematical sense. But this is certainly a great solution.
But I can do without lookbehind !
Expression of words that do not end with JJ
The fact that it does not contain these two letters at the end makes the question easier. Just see the response response to see the work that denies a subword anywhere.
In order not to end with JJ
, we have 4 alternatives:
The line is blank so it matches with ^$
The line contains exactly one character, so ^.$
The last character is not J, ^.*[^J]$
The penultimate character is not J, ^.*[^J].$
So, the following expression matches this:
^$|^.$|^.*[^J]$|^.*[^J].$
Ugly, is not it? But fortunately it can be simplified:
^(.|.*([^J]|[^J].))?$
I could have simplified even more [^J]|[^J].
, but then I would lose the format to be used in the next expression
Expression of words that do not end with M3
In order not to end with JJ
, we have 4 alternatives:
The line is blank so it matches with ^$
The line contains exactly one character, so ^.$
The last character is not 3, '^. * [^ 3] $
The penultimate character is not M, ^.*[^M].$
I could put the ugly version and then simplified it, but I can also abbreviate it:
^(.|.*([^3]|[^M].))?$
Putting it all together
To put everything together, there are some special cases to consider:
Can end in J
if the penultimate letter is M
Can end in 3
if the penultimate letter is J
Moreover, agglutinating the denied lists does the service. These would be the only cases not treated by the previous abstraction.
^(.|.*([^J3]|[^JM].|J3|MJ))?$