我需要接受这个字符串:
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)**");
给我组索引的替换模式是什么?
您可以使用带有 a 的方法Regex.Replace
以及MatchEvaluator
一个计数器变量:
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 =>
部分是MatchEvaluator
. 在这种情况下,不需要使用Match
(which is m
); 我们只想返回连接的结果并增加计数器。
如果你想要一个单行解决方案,你可以做类似的事情,但对于大字符串可能会很慢,因为它必须找到“?”的计数。每场比赛
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"
这是我可以看到在不声明外部变量的情况下获取索引的唯一方法。
我使用 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();
我想我可能有什么...
这个想法是首先将每个索引放在您想要索引的每个位置:
Ñ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Ñ
...
未经测试:
int n, i=1; while( (n=input.IndexOf("?")) != -1) { input = input.Substring(0,n-1) + "@p" + (++i) + input.Substring(n+1); }
一条较长的线,但并非完全不合理。