C#中普通引号转智能引号:正则表达式实现方案咨询
智能引号替换方案:正则实现与效率对比
一、正则表达式实现方案
根据你提供的转换规则(仅替换短语/句子开头/结尾的引号,单词中间的引号保留),可以分两步用正则完成替换,逻辑和原循环代码一致:
C# 代码实现
using System.Text.RegularExpressions; public string ConvertToSmartQuotes(string richText) { // 第一步:替换开头的左智能引号 string leftReplaced = Regex.Replace(richText, @"(^|\s)(\p{P}*)(['"])", m => { // 保留前缀(空格+标点),替换引号为左智能引号 string prefix = m.Groups[1].Value + m.Groups[2].Value; char originalQuote = m.Groups[3].Value[0]; char smartQuote = originalQuote == '\'' ? '‘' : '“'; return prefix + smartQuote; }); // 第二步:替换结尾的右智能引号 string result = Regex.Replace(leftReplaced, @"(['"])(\p{P}*)(\s|$)", m => { // 替换引号为右智能引号,保留后缀(标点+空格/结尾) char originalQuote = m.Groups[1].Value[0]; char smartQuote = originalQuote == '\'' ? '’' : '”'; string suffix = m.Groups[2].Value + m.Groups[3].Value; return smartQuote + suffix; }); return result; }
正则说明
- 左引号匹配规则:
(^|\s)(\p{P}*)(['"])
匹配字符串开头或空格后的任意数量标点,再匹配原引号,确保处于“短语开头序列”中的引号被替换为左智能引号 - 右引号匹配规则:
(['"])(\p{P}*)(\s|$)
匹配原引号后接任意数量标点,再匹配空格或字符串结尾,确保处于“短语结尾序列”中的引号被替换为右智能引号
二、循环方案 vs 正则方案效率对比
循环方案优势
你的原循环方案(基于StringBuilder)在大文本量场景下效率更高,原因如下:
- 时间复杂度与常数因子:循环是线性遍历两次(O(n)时间复杂度),且
StringBuilder的字符修改是直接内存操作,几乎无额外开销;正则表达式需要解析正则规则、执行匹配逻辑,即使是简单正则,常数因子也远高于循环。 - 内存开销:正则替换会生成多个中间字符串(每次
Replace都会创建新字符串),而StringBuilder是在原内存缓冲区修改,内存占用更低。
正则方案优势
正则方案代码更简洁、可读性更强,维护成本低;如果你的游戏文本单段长度不超过几MB,性能差异几乎可以忽略,此时正则方案的开发效率优势更明显。
三、原循环代码优化建议
你的原循环代码已经很高效,可做微小优化:合并两次遍历为一次,提前记录所有需要替换的位置,减少遍历次数:
public string ConvertToSmartQuotesOptimized(string richText) { StringBuilder builder = new StringBuilder(richText); int length = builder.Length; // 记录左引号替换位置 bool isLeftQuoteState = true; // 记录右引号替换位置(先标记,最后统一替换) List<int> rightQuotePositions = new List<int>(); char[] chars = builder.ToString().ToCharArray(); // 第一次遍历:标记左引号和待替换的右引号位置 for (int i = 0; i < length; i++) { if (isLeftQuoteState) { if (chars[i] == '\'') { chars[i] = '‘'; } else if (chars[i] == '\"') { chars[i] = '“'; } else if (!char.IsPunctuation(chars[i])) { isLeftQuoteState = false; } } else if (chars[i] == ' ') { isLeftQuoteState = true; } // 反向逻辑:标记右引号位置 bool isRightQuoteState = false; int j = length - 1 - i; if (j >= 0) { if (j == length - 1) { isRightQuoteState = true; } else if (chars[j + 1] == ' ') { isRightQuoteState = true; } else if (char.IsPunctuation(chars[j + 1])) { // 继承前一个位置的状态 isRightQuoteState = rightQuotePositions.Contains(j + 1); } if (isRightQuoteState && (chars[j] == '\'' || chars[j] == '\"')) { rightQuotePositions.Add(j); } } } // 替换右引号 foreach (int pos in rightQuotePositions) { if (chars[pos] == '\'') { chars[pos] = '’'; } else if (chars[pos] == '\"') { chars[pos] = '”'; } } return new string(chars); }
注:此优化仅适合极端大文本场景,普通场景下原循环代码的可读性更好,无需修改。
内容的提问来源于stack exchange,提问作者Riley Sampson
相关产品推荐
相关产品推荐

