This is the answer that I came up with. It's simple and works well with strings up to at least severl thousand characters.
Example 1:
Regex rx = new Regex( @"\\[uU]([0-9A-F]{4})" );
result = rxx.Replace( result, match => ((char) Int32.Parse(match.Value.Substring(2), NumberStyles.HexNumber)).ToString() );
Example 2:
Regex rx = new Regex( @"\\[uU]([0-9A-F]{4})" );
result = rx.Replace( result, delegate (Match match) { return ((char) Int32.Parse(match.Value.Substring(2), NumberStyles.HexNumber)).ToString(); } );
The first example shows the repacement being made using a Lambda Expression (C# 3.0) and the second uses a
delegate which should work with C# 2.0.
To break down what's going on here, first we create a regular expression:
new Regex( @"\\[uU]([0-9A-F]{4})" );
Then we call Replace() with the string 'result' and an anonymous method (Lambda expression in the first example and the delegate in the second - the delegate could also be a regular method) that converts each regular expression that is found in the string.
The unicode escape is processed like this:
((char) Int32.Parse(match.Value.Substring(2), NumberStyles.HexNumber)).ToString(); } );
Get the string representing the number part of the escape (skip the first two characters).
match.Value.Substring(2)
Parse that string using Int32.Parse() which takes the string and the number format that Parse() function should expect which in this case is a hex number.
NumberStyles.HexNumber
Then we cast the resulting number to a unicode character
(char)
and finaly we call ToString() on the unicode character which gives us it's string representation which is the value passed back to Replace()
.ToString()
Note, instead of grabbing the text to be converted with a Substring call you could use the match parameter's GroupCollection, and a subexpressions in the regular expression to capture just
the number ('2320') but that's more complicated and less readable.