C# Regular Expression Recipes—Augmenting the Basic String Replacement Function
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp) Developer Training, Visual Studio
| CSharp-Online.NET:Articles |
| C# Articles |
| © 2004 O'Reilly & Assoc., Inc. |
Contents |
Augmenting the Basic String Replacement Function
Problem
You need to replace character patterns within the target string with a new string. However, in this case, each replacement operation has a unique set of conditions that must be satisfied in order to allow the replacement to occur. Consider, for example, that you receive a string in the form of XML (or possibly HTML). You wish to modify an attribute of a specific XML tag to a particular number, but only if that number is within a specified range (or possibly outside of a particular range).
Solution
Use the overloaded instance Replace method that accepts a MatchEvaluator delegate
along with its other parameters. The MatchEvaluator delegate, which is a callback
method that overrides the default behavior of the Replace method, is shown here:
using System; using System.Text.RegularExpressions; public static string MatchHandler(Match theMatch) { // Handle Top property of the Property tag if (theMatch.Value.StartsWith("<Property")) { long topPropertyValue = 0; // Obtain the numeric value of the Top property Match topPropertyMatch = Regex.Match(theMatch.Value, "Top=\"([-]*\\d*)"); if (topPropertyMatch.Success) { if (topPropertyMatch.Groups[1].Value.Trim( ).Equals("")) { // If blank, set to zero return (theMatch.Value.Replace("Top=\"\"", "Top=\"0\"")); } else if (topPropertyMatch.Groups[1].Value.Trim( ).Equals("-")) { // If only a negative sign (syntax error), set to zero return (theMatch.Value.Replace("Top=\"-\"", "Top=\"0\"")); } else { // We have a valid number // Convert the matched string to a numeric value topPropertyValue = long.Parse( topPropertyMatch.Groups[1].Value, System.Globalization.NumberStyles.Any); // If the Top property is out of the specified // range, set it to zero if (topPropertyValue < 0 || topPropertyValue > 5000) { return (theMatch.Value.Replace("Top=\"" + topPropertyValue + "\"", "Top=\"0\"")); } } } } return (theMatch.Value); }
The callback method for the Replace method is shown here:
public static void ComplexReplace(string matchPattern, string source) { MatchEvaluator replaceCallback = new MatchEvaluator(MatchHandler); Regex RE = new Regex(matchPattern, RegexOptions.Multiline); string newString = RE.Replace(source, replaceCallback); Console.WriteLine("Replaced String = " + newString); }
To use this callback method with the static Replace method, modify the previous ComplexReplace method as follows:
public void ComplexReplace(string matchPattern, string source) { MatchEvaluator replaceCallback = new MatchEvaluator(MatchHandler); string newString = Regex.Replace(source, matchPattern, replaceCallback); Console.WriteLine("Replaced String = " + newString); }
where source is the original string to run the replace operation against, and
matchPattern is the regular expression pattern to match in the source string.
If the ComplexReplace method is called from the following code:
public static void TestComplexReplace( ) { string matchPattern = "<.*>"; string source = @"<?xml version=""1.0\"" encoding=\""UTF-8\""?> <Window ID=""Main""> <Control ID=""TextBox""> <Property Top=""-100"" Left=""0"" Text=""BLANK""/> </Control> <Control ID=""Label""> <Property Top=""99990"" Left=""0"" Caption=""Enter Name Here""/> </Control> </Window>"; ComplexReplace(matchPattern, source); }
only the Top attributes of the Property tags are changed from their original values to 0.
The result of this replace action will change only the Top property value of a Property
tag to zero if it is less than zero or greater than 5000. Any other tag that contains a Top
property will remain unchanged. The following two lines of the source string will be
changed from:
<Property Top="100" Left="0" Text="BLANK"/> <Property Top="99999" Left="0" Caption="Enter Name Here"/>
to:
<Property Top="100" Left="0" Text="BLANK"/> <Property Top="0" Left="0" Caption="Enter Name Here"/>
Discussion
The MatchEvaluator delegate, which is automatically invoked when it is supplied as a
parameter to the Regexp class’s Replace method, allows for custom replacement of
each string that conforms to the regular expression pattern.
If the current Match object is operating on a Property tag whose Top property is out of
the specified range, the code within the MatchHandler callback method returns a new
modified string. Otherwise, the currently matched string is returned unchanged. This
ability allows you to override the default Replace functionality by replacing only that
part of the source string that meets certain criteria. The code within this callback
method gives you some idea of what can be accomplished using this replacement
technique.
To make use of this callback method, we need a way to call it from the
ComplexReplace method. First, a variable of type System.Text.RegularExpressions.
MatchEvaluator is created. This variable (replaceCallback) is the delegate that is
used to call the MatchHandler method:
MatchEvaluator replaceCallback = new MatchEvaluator(MatchHandler);
Finally, the Replace method is called with the reference to the MatchEvaluator delegate
passed in as a parameter:
string newString = RE.Replace(source, replaceCallback);
See Also
See the ".NET Framework Regular Expressions" topic in the MSDN documentation.
|

