.NET Framework 4.8下支持忽略大小写全词匹配的字符串替换方案
问题根因
原实现中使用的\b正则单词边界仅匹配\w(字母、数字、下划线)与\W(非\w字符)的交界位置,当待匹配词本身以非\w字符开头/结尾时,\b无法匹配到对应的边界,这就是特殊字符全词匹配失效的核心原因。同时原边界规则也无法处理目标词与标点相邻的全词匹配场景。
修复方案一:正则优化版(兼容.NET Framework 4.8)
仅调整全词匹配的边界逻辑,用自定义环视规则替代原生\b,匹配逻辑完全符合需求:
using System; using System.Text.RegularExpressions; public static class StringExtensions { public static string Replace(this string s, string word, string by, bool IgnoreCase, bool WholeWord) { // 空输入直接返回 if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(word)) return s; RegexOptions regexOptions = RegexOptions.None; if (IgnoreCase) regexOptions |= RegexOptions.IgnoreCase; regexOptions |= RegexOptions.CultureInvariant; string pattern = Regex.Escape(word); if (WholeWord) { // 自定义全词边界:前后不能是字母/数字,天然支持句首、句尾、与标点相邻的场景 pattern = @"(?<!\p{L}|\p{N})" + pattern + @"(?!\p{L}|\p{N})"; } return Regex.Replace(s, pattern, by, regexOptions); } }
效果验证
- 替换逗号场景:输入
"Apple , Mango , Banana.",替换,为" and ",全词匹配开启,输出为"Apple and Mango and Banana." - 替换单词场景:输入
"She is Mari and she is Marijane. Mari is at home.",替换"Mari"为"Mira",全词匹配开启,输出为"She is Mira and she is Marijane. Mira is at home.",不会误改Marijane
修复方案二:纯字符串实现版(无正则依赖,性能更优)
适合高频调用场景,无正则解析开销,逻辑完全可控:
using System; using System.Collections.Generic; public static class StringExtensions { public static string Replace(this string s, string word, string by, bool IgnoreCase, bool WholeWord) { if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(word) || word.Length > s.Length) return s; StringComparison comparison = IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; List<int> matchIndexes = new List<int>(); int wordLength = word.Length; int i = 0; while (i <= s.Length - wordLength) { if (string.Compare(s, i, word, 0, wordLength, comparison) == 0) { bool isMatch = true; if (WholeWord) { // 左边界校验:左侧有字符时不能是字母/数字 if (i > 0 && char.IsLetterOrDigit(s[i - 1])) isMatch = false; // 右边界校验:右侧有字符时不能是字母/数字 if (isMatch && i + wordLength < s.Length && char.IsLetterOrDigit(s[i + wordLength])) isMatch = false; } if (isMatch) { matchIndexes.Add(i); i += wordLength; // 跳过已匹配段避免重叠匹配 continue; } } i++; } if (matchIndexes.Count == 0) return s; // 高效构建结果字符串 char[] result = new char[s.Length + matchIndexes.Count * (by.Length - wordLength)]; int resultPos = 0; int lastPos = 0; foreach (int idx in matchIndexes) { s.CopyTo(lastPos, result, resultPos, idx - lastPos); resultPos += idx - lastPos; by.CopyTo(0, result, resultPos, by.Length); resultPos += by.Length; lastPos = idx + wordLength; } s.CopyTo(lastPos, result, resultPos, s.Length - lastPos); return new string(result); } }
内容的提问来源于stack exchange,提问作者Jaspreet Sidhu
相关产品推荐
相关产品推荐

