替换字符串中的第N个正则表达式匹配

时间:2017-11-09 11:35:59

标签: c# regex

我知道在SO上有很多这样的问题,但是我找不到解释他们如何实现模式以返回第N场比赛的问题。我看到的所有答案只是给OP提供了最少解释的代码。

我所知道的是,您需要在{X}是您想要返回的数字出现的模式中实现此X

所以我想在两个string之间匹配一个chars,我似乎已经能够实现这一点。

要测试的字符串看起来像这样,

  

"=StringOne&=StringTwo&=StringThree&=StringFour&"

"[^/=]+(?=&)"

同样,在尽可能多地阅读之后,这个模式也将返回所有匹配,

[^/=]+(?=&){1}

由于{1}是默认值,因此在上述模式中是多余的。 但我不能这样做,

[^/=]+(?=&){2}

因为它不会像我期待的那样返回第3场比赛。

那么有人可以把我推向正确的方向,并解释如何获得所需的模式以找到所需的匹配事件?

1 个答案:

答案 0 :(得分:1)

纯正的正则表达方式是可行的,但如果你的模式很复杂,那么效率并不高。

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# demoregex demo

enter image description here

正则表达式详细信息

  • ^ - 字符串开头
  • (=(?:[^=&]+&=){1}) - 第1组捕获:
    • = - =符号
    • (?:[^=&]+&=){1} -
    • 出现1次(此号码是动态生成的)
    • [^=&]+ - 除=&以外的一个或多个字符(注意,以防字符串可能包含=和{{ 1}},用&替换它并将.*?选项传递给正则表达式编译器更安全。
    • RegexOptions.Singleline - &=子字符串。
  • &= - 除[^=&]+=以外的一个或多个字符

替换模式中的&将组1的内容插回到结果字符串中。

作为替代方案,我可以建议在每次匹配时引入计数器和增量,并且只有在计数器等于您指定的匹配项时才替换该计数器。

使用

${1}

请参阅C# demo

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& cnt内的匹配评估器内递增,Regex.Replace被分配了当前的m对象。如果Match等于cnt,则会发生替换,否则,将粘贴整个匹配(使用idx_to_replace)。

另一种方法是迭代匹配,一旦找到第N个匹配,通过在匹配之前将字符串拆分为部分并在匹配完成替换之后将其替换为循环来替换它:

m.Value

请参阅another C# demo

这可能会更快,因为引擎不必找到所有匹配。