According to the .Net documentation on Regex, one can use Character Class Subtractions, in the form of:
[base_group - [excluded_group]]
Both base_group and excluded_group can be positive and negative character groups.
However, see the following #fsharp code:
let pattern = "([^A-F-[C-D]])"
"ABCDEFG".ToCharArray()
|> Array.iter(fun s -> printfn "%c - %b" s ((Regex.Match (string(s), pattern)).Success))
With the following output:
A - false
B - false
C - false
D - false
E - false
F - false
G - true
I was expecting true on "C" and "D".
The following pattern gives the same result: "([^A-F-[CD]])" (note I changed character range [C-D] into characterset [CD])
Am I doing this the right way?
I did a few extra tests, and this code:
let pattern = "([^A-F-[^KL]])"
"ABCDEFGHIJKLMNOP".ToCharArray()
|> Array.iter(fun s -> printfn "%c - %b" s ((Regex.Match (string(s), pattern)).Success))
Gives this result:
A - false
B - false
C - false
D - false
E - false
F - false
G - false
H - false
I - false
J - false
K - true
L - true
M - false
N - false
O - false
P - false
Which suggests that I might gotten the interpretation incorrect. The spec says:
Character class subtraction yields a set of characters that is the result of excluding the characters in one character class from another character class.
So the root of confusion might be that I expected the subtraction operation to work during the construction of the character class, while it works on character class constructs.
With this interpretation, if I have a pattern like this: [^A-F-[C-D]] This does not mean that "C-D" should be subtracted from "A-F". It means that we match true on any character except "A-F" and we subtract a match on "C-D" - for which it already did not match. That's why it appears ineffective.
So [^A-F] is character class in its own right, it's atomic and a subtraction operation works on the resulting set of characters.
The second pattern demonstrates this interpretation even better: [^A-F-[^KL]] Read like this. We match true for anything except "A-F" and we subtract matches on anything except "KL". Simple set-subtraction and this result in "KL".