纯正则表达式方法是可能的,但如果您的模式很复杂,则效率不是很高。
var s = "=StringOne&=StringTwo&=StringThree&=StringFour&";
var idx = 2; // Replace this occurrence
var result = Regex.Replace(s, $@"^(=(?:[^=&]+&=){{{idx-1}}})[^=&]+", "${1}REPLACED");
Console.WriteLine(result); // => =StringOne&=REPLACED&=StringThree&=StringFour&
参见this C# demo 和regex demo。
正则表达式详细信息
-
^ - 字符串开头
-
(=(?:[^=&]+&=){1}) - 第 1 组捕获:
-
= - = 符号
-
(?:[^=&]+&=){1} - 出现 1 次(此数字是动态生成的)
-
[^=&]+ - 除= 和& 之外的1 个或多个字符(注意 如果字符串可能包含= 和&,则将其替换为@987654338 会更安全@ 并将RegexOptions.Singleline 选项传递给正则表达式编译器)
-
&= - &= 子字符串。
-
[^=&]+ - 除了 = 和 & 之外的 1 个或多个字符
替换模式中的${1} 将第 1 组的内容插入回结果字符串中。
作为替代方案,我可以建议引入一个计数器并在每次匹配时递增,并且仅在计数器等于您指定的匹配出现时替换一个。
使用
var s = "=StringOne&=StringTwo&=StringThree&=StringFour&";
var idx_to_replace = 2; // Replace this occurrence
var cnt = 0; // Counter
var result = Regex.Replace(s, "[^=]+(?=&)", m => { // Match evaluator
cnt++; return cnt == idx_to_replace ? "REPLACED" : m.Value; });
Console.WriteLine(result);
// => =StringOne&=REPLACED&=StringThree&=StringFour&
请参阅C# demo。
cnt 在 Regex.Replace 内的匹配评估器内递增,m 被分配当前的 Match 对象。当cnt 等于idx_to_replace 时,替换发生,否则,整个匹配被粘贴回来(m.Value)。
另一种方法是遍历匹配项,一旦找到第 N 个匹配项,通过将字符串拆分为匹配前和匹配后的部分来替换它,一旦替换完成,则退出循环:
var s = "=StringOne&=StringTwo&=StringThree&=StringFour&";
var idx_to_replace = 2; // Replace this occurrence
var cnt = 0; // Counter
var result = string.Empty; // Final result variable
var rx = "[^=]+(?=&)"; // Pattern
for (var m=Regex.Match(s, rx); m.Success; m = m.NextMatch())
{
cnt++;
if (cnt == idx_to_replace) {
result = $"{s.Substring(0, m.Index)}REPLACED{s.Substring(m.Index+m.Length)}";
break;
}
}
Console.WriteLine(result); // => =StringOne&=REPLACED&=StringThree&=StringFour&
见another C# demo。
这可能会更快,因为引擎不必找到所有个匹配项。