在C#中使用Regex替换时忽略字符串引号内的匹配项
批量替换VB.NET表达式中的非短路语法为短路版本(排除字符串引号内内容)
问题背景
我负责的应用中,系统管理员可创建自定义字段并配置VB.NET语法的计算表达式,这些表达式以字符串形式存储在CustomField对象中。现需批量清理这些表达式,将非短路的函数和运算符替换为短路版本,使用.NET C#的Regex.Replace()实现。
替换需求
- 替换规则:
IIF→IF,And→AndAlso,Or→OrElse - 匹配忽略大小写,适配管理员输入的大小写不统一语法
IIF函数需匹配两种格式:IIF(和IIF后跟任意空白字符再跟(And/Or运算符仅匹配前后带空格的实例,且禁止替换字符串引号内的对应内容
初始方案的局限
最初的代码能正确处理IIF的匹配,但无法区分引号内外的And/Or,会误替换字符串中的and/or,不符合需求。
初始代码:
foreach (CustomFieldInfo customField in Session.ConfigurationManager.GetCustomFields(false)) { string fieldCalcStr = customField.Calculation.Trim(); if (string.IsNullOrEmpty(fieldCalcStr)) continue; fieldCalcStr = Regex.Replace(fieldCalcStr, @"IIF\(|IIF *\(", "IF(", RegexOptions.IgnoreCase); fieldCalcStr = Regex.Replace(fieldCalcStr, " AND ", " AndAlso ", RegexOptions.IgnoreCase); fieldCalcStr = Regex.Replace(fieldCalcStr, " OR ", " OrElse ", RegexOptions.IgnoreCase); customField.Calculation = fieldCalcStr; }
最终解决方案
通过Regex.Split()将表达式拆分为引号内的字符串片段和非引号内的代码片段,仅对非引号内的部分执行替换操作,彻底解决了引号内内容误替换的问题。
最终代码:
Dictionary<string, string> patternReplacementDict = new Dictionary<string, string>(); patternReplacementDict.Add(@"(?:IIF\s*[(])", "IF("); patternReplacementDict.Add(@"(?: AND )", " AndAlso "); patternReplacementDict.Add(@"(?: OR )", " OrElse "); foreach (CustomFieldInfo customField in Session.ConfigurationManager.GetCustomFields(false)) { string calcStr = customField.Calculation.Trim(); if (string.IsNullOrEmpty(calcStr)) continue; string[] calcStrArray = Regex.Split(calcStr, "(\"[^\"]+\")"); string newCalcStr = string.Empty; foreach (string str in calcStrArray) { if (!str.StartsWith("\"")) { string newStr = str; foreach (KeyValuePair<string, string> kvp in patternReplacementDict) { newStr = Regex.Replace(newStr, kvp.Key, kvp.Value, RegexOptions.IgnoreCase); } newCalcStr += newStr; } else { newCalcStr += str; } } customField.Calculation = newCalcStr; }
输入输出示例
输入
IIF([FIELD1] = "This ""quoted text inside string quotes"" and that" AnD [FIELD2] = "This or that", "Value 1", iiF ([FIELD3] = "This and that" aNd [FIELD4] = "This or that", "Value 2", IIF([FIELD4] = "This and that" Or [FIELD5] = "This or that", "Value 3", Iif ([FIELD6] = "This and that" oR [FIELD7] = "This or that", "Value 4", ""))))
输出
IF([FIELD1] = "This ""quoted text inside string quotes"" and that" AndAlso [FIELD2] = "This or that", "Value 1", IF([FIELD3] = "This and that" AndAlso [FIELD4] = "This or that", "Value 2", IF([FIELD4] = "This and that" OrElse [FIELD5] = "This or that", "Value 3", IF([FIELD6] = "This and that" OrElse [FIELD7] = "This or that", "Value 4", ""))))
内容的提问来源于stack exchange,提问作者lsargent
相关产品推荐
相关产品推荐

