【问题标题】:Regex replace character with index of match正则表达式用匹配索引替换字符
【发布时间】:2013-02-19 06:12:29
【问题描述】:

我需要这个字符串:

book_id = ? and author_id = ? and publisher_id = ?

并把它变成这个字符串:

book_id = @p1 and author_id = @p2 and publisher_id = @p3

使用此代码:

Regex.Replace(input, @"(\?)", "@p **(index of group)**");

给我组索引的替换模式是什么?

【问题讨论】:

  • 单行代码很简单 - 只需在源代码上执行 Replace("\n", " ")
  • 非常可爱的回应 ;p
  • 我可以在第三个参数的替换模式中用正则表达式解决它吗?

标签: c# regex replace


【解决方案1】:

我想我可能有什么...

这个想法是首先将每个索引放在您想要索引的每个位置:

Ñ123456Ñ

对于这个例子,总共有 6 个项目要索引,所以它是由 Ñ(或查找文本中没有的其他字符)包围的所有不超过 6 的数字。

然后您手动制作第一个 Ñ1Ñ,这样正则表达式就有一个起点。 有了这个,算法可以找到最后一个索引并使用它来确定下一个索引:

查找: (Ñ)([0-9])(Ñ)(([^Ñ]|\r?\n)*?)(Ñ)([0-9]*)\2([0-9])([0-9]*)(Ñ)

替换: $1$2$3$4$6$8$10

文字示例:

Ñ1Ñ
Ñ123456Ñ
Ñ123456Ñ
Ñ123456Ñ
Ñ123456Ñ
Ñ123456Ñ

更换一次后:

Ñ1Ñ
Ñ2Ñ
Ñ123456Ñ
Ñ123456Ñ
Ñ123456Ñ
Ñ123456Ñ

再次更换后:

Ñ1Ñ
Ñ2Ñ
Ñ3Ñ
Ñ123456Ñ
Ñ123456Ñ
Ñ123456Ñ

“全部替换”功能对此不起作用,因为它必须逐个查找和替换,但我认为它可以完成工作。

然后你只需要删除所有临时 Ñ 字符就可以了。

免责声明:解决“中间”文本中的换行符的部分 - \r?\n - 用于 Atom 编辑器,因此可能需要针对其他情况进行一些调整。我相信它实际上可以完全删除,因为它包含在 [^Ñ] 中,但我不确定它是否适用于其他系统。


对于多于一位的索引:

查找: (Ñ)([0-9]{2})(Ñ)(([^Ñ]|\r?\n)*?)(Ñ)([0-9][0-9])*\2([0-9]{2})([0-9][0-9])*(Ñ)

替换: $1$2$3$4$6$8$10

文字示例:

Ñ01Ñ
Ñ0102030405060708091011121314151617Ñ
Ñ0102030405060708091011121314151617Ñ
Ñ0102030405060708091011121314151617Ñ
...

【讨论】:

  • 也许您可以添加如何将此算法与提供的代码sn-p OP结合起来?
  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

我使用 StringBuilder 的解决方案还不错,但不是最快也不是最优雅的:(

var count = 1;
var sb = new StringBuilder(input);
for (int i = 0; i < sb.Length; i++)
{
    if (sb[j] == '?')
    {
        sb.Remove(i, 1);
        sb.Insert(i, "@p" + (count++));
        i += 3;
    }
}
result = sb.ToString();

【讨论】:

    【解决方案3】:

    如果您想要一个单行解决方案,您可以执行类似的操作,但对于大字符串可能会很慢,因为它必须找到“?”的计数。每场比赛

     var result = Regex.Replace(input, @"\?", m => "@p" + input.Take(m.Index).Count(c => c == '?'));
    

    返回"book_id = @p0 and author_id = @p1 and publisher_id = @p2"

    这是我能看到的在不声明外部变量的情况下获取索引的唯一方法。

    【讨论】:

      【解决方案4】:

      您可以使用带有MatchEvaluatorRegex.Replace method,以及一个计数器变量:

      string input = "book_id = ? and author_id = ? and publisher_id = ?";
      string pattern = @"\?";
      int count = 1;
      string result = Regex.Replace(input, pattern, m => "@p" + count++);
      

      m =&gt; 部分是MatchEvaluator。在这种情况下,不需要使用Match(即m);我们只想返回连接的结果并增加计数器。

      【讨论】:

      • 我们对这个回应越来越热情了。但是我需要在替换模式中包含索引计算。
      • @schmij 你能解释一下你所说的组指数计算是什么意思吗?我的方法给出的结果类似于您的问题。如果您需要输入中出现? 的索引,您可以在lambda 中使用m.Index 而不是count 变量。或者,如果模式使用组 @"(\?)",您可以使用 m.Groups[1].Index。我认为这不符合您的要求。也许输出的另一个示例将有助于阐明您所追求的。
      • 我正在寻找一种特定于正则表达式的替换模式来生成匹配组的索引。
      • @SenJacob 发生这种情况的唯一方法是如果您还使用RegexOptions.RightToLeft。上面的代码有一个有序的结果。
      • @AhmadMageed 是的,这很有意义。我正在处理添加了 RTL 选项的希伯来语文本。好收获!
      【解决方案5】:

      未经测试:

      int n, i=1; while( (n=input.IndexOf("?")) != -1) { input = input.Substring(0,n-1) + "@p" + (++i) + input.Substring(n+1); }
      

      一条较长的线,但并非完全不合理。

      【讨论】:

      • 是的,只有一行……但我不完全确定 OP 的目标是什么……
      猜你喜欢
      • 2015-11-30
      • 2016-05-23
      • 2022-12-01
      • 1970-01-01
      • 2015-01-04
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 2021-09-17
      相关资源
      最近更新 更多