C# 如何独家更换?
好吧,我有一个很明显但显然不重要的问题要解决 假设我有一个简单的字符串C# 如何独家更换?,c#,regex,string,replace,C#,Regex,String,Replace,好吧,我有一个很明显但显然不重要的问题要解决 假设我有一个简单的字符串ab 现在我想用b替换a,用a替换b,所以我最后得到了ba 动手解决的办法是连续进行两次替换。但根据顺序,结果可能是aa或bb 显然,生产环境将不得不处理比两个更复杂的字符串和更多的替换,但问题仍然存在 我的一个想法是保留我替换某物的位置。但是,当更换的针头长度与原来的针头长度不同时,我马上就放弃了 这是一个普遍的问题,但我正在与C#合作。下面是我想到的一些代码: string original = "abc"; Regex
ab
现在我想用
b
替换a
,用a
替换b
,所以我最后得到了ba
动手解决的办法是连续进行两次替换。但根据顺序,结果可能是aa
或bb
显然,生产环境将不得不处理比两个更复杂的字符串和更多的替换,但问题仍然存在
我的一个想法是保留我替换某物的位置。但是,当更换的针头长度与原来的针头长度不同时,我马上就放弃了
这是一个普遍的问题,但我正在与C#合作。下面是我想到的一些代码:
string original = "abc";
Regex[] expressions = new Regex[]
{
new Regex("a"), //replaced by ab
new Regex("b") //replaced by c
};
string[] replacements = new string[]
{
"ab",
"c"
};
for (int i = 0; i < expressions.Length; i++)
original = expressions[i].Replace(original, replacements[i]);
//Expected result: abcc
//Actual result: accc <- the b is replaced by c in the second pass.
string original=“abc”;
正则表达式[]表达式=新正则表达式[]
{
新正则表达式(“a”),//替换为ab
新正则表达式(“b”)//替换为c
};
字符串[]替换=新字符串[]
{
“ab”,
“c”
};
for(int i=0;i(\ba\b)
表示匹配字母a
,并且仅匹配字母a
,则accc,而ab
将不匹配。与b
类似,它将是(\bb\b)
编辑2:
答案更改为反映要匹配的可变长度,这将根据要检查的模式顺序进行匹配,检查模式,然后移动到新字符串
string original = "a bc";
Regex[] expressions = new Regex[] {
new Regex(@"a"), //replaced by ab
new Regex(@"b"), //replaced by c
};
string[] replacements = new string[] {
"ab",
"c",
};
string newString = string.Empty;
string workingString = string.Empty;
// Position of start point in string
int index = 0;
// Length to retrieve
int length = 1;
while(index < original.Length) {
// Retrieve a piece of the string
workingString = original.Substring(index, length);
// Whether the expression has been matched
bool found = false;
for(int i = 0; i < expressions.Length && !found; i++) {
if(expressions[i].Match(workingString).Success) {
// If expression matched, add the replacement value to the new string
newString += expressions[i].Replace(workingString, replacements[i]);
// Mark expression as found
found = true;
}
}
if(!found) {
// If not found, increase length (check for more than one character patterns)
length++;
// If the rest of the entire string doesn't match anything, move the character at **index** into the new string
if(length >= (original.Length - index)) {
newString += original.Substring(index, 1);
index++;
length = 1;
}
}
// If a match was found, start over at next position in string
else {
index += length;
length = 1;
}
}
string original=“a bc”;
正则表达式[]表达式=新正则表达式[]{
新正则表达式(@“a”),//替换为ab
新的正则表达式(@“b”),//替换为c
};
字符串[]替换=新字符串[]{
“ab”,
“c”,
};
string newString=string.Empty;
string workingString=string.Empty;
//字符串中起始点的位置
int指数=0;
//要检索的长度
整数长度=1;
while(索引<原始长度){
//取回一根绳子
workingString=原始.Substring(索引,长度);
//表达式是否匹配
bool-found=false;
for(int i=0;i=(original.length-index)){
newString+=original.Substring(索引,1);
索引++;
长度=1;
}
}
//若找到匹配项,则从字符串中的下一个位置重新开始
否则{
指数+=长度;
长度=1;
}
}
这里有一个解决方案。对字符串尝试所有正则表达式,对最早的匹配进行替换,然后对字符串的其余部分进行递归。如果需要更快但更复杂,可以在开始时要求所有的匹配()
,然后从左到右处理它们,在用更长和更短的字符串替换表达式时调整它们的索引,并丢弃任何重叠
using System;
using System.IO;
using System.Text.RegularExpressions;
class MultiRegex {
static String Replace(String text, Regex[] expressions,
String[] replacements, int start=0)
{
// Try matching each regex; save the first match
Match firstMatch = null;
int firstMatchingExpressionIndex = -1;
for (int i = 0; i < expressions.Length; i++) {
Regex r = expressions[i];
Match m = r.Match(text, start);
if (m.Success
&& (firstMatch == null || m.Index < firstMatch.Index))
{
firstMatch = m;
firstMatchingExpressionIndex = i;
}
}
if (firstMatch == null) {
/* No matches anywhere */
return text;
}
// Replace text, then recurse
String newText = text.Substring(0, firstMatch.Index)
+ replacements[firstMatchingExpressionIndex]
+ text.Substring(firstMatch.Index + firstMatch.Length);
return Replace(newText, expressions, replacements,
start + replacements[firstMatchingExpressionIndex].Length);
}
public static void Main() {
Regex[] expressions = new Regex[]
{
new Regex("a"), //replaced by ab
new Regex("b") //replaced by c
};
string[] replacements = new string[]
{
"ab",
"c"
};
string original = "a b c";
Console.WriteLine(
Replace(original, expressions, replacements));
// Should be "baz foo bar"
Console.WriteLine(Replace("foo bar baz",
new Regex[] { new Regex("bar"), new Regex("baz"),
new Regex("foo") },
new String[] { "foo", "bar", "baz" }));
}
}
如果您谈论的是简单的一对一转换,那么转换为字符数组并进行切换可能是理想的,但是您似乎在寻找更复杂的替换
基本上,技巧是创建一个中间角色来标记临时角色。这里不是显示实际代码,而是字符串在转换时的样子:
ab
%1b
%1%2
b%2
ba
因此,基本上,将%%
替换为%%
,然后将第一个匹配项替换为%1
,依此类推。完成所有操作后,将%1
替换为其输出,依此类推,最后将%%
替换为%%
但是要小心,如果你能保证你的中间语法不会污染你的输入,你就可以了,如果你不能,你就需要使用一些技巧来确保你的前面没有奇数个%
。(因此,%%a
将匹配,但%%a
将不匹配,因为这将意味着特殊值%a
)当您有两个以上的字符时,替换如何工作?如果您的替换仅为单个字符(替换的内容和替换的内容),这是一个单遍算法-对于每个输入字符,如果需要替换,则输出替换字符,否则只输出字符。可能最容易建立一个简单的替换表来引用,除非您只替换几个字符…@Bob。我已经添加了一些。@twalberg针和替代品可能不止一个字符。即使针和更换长度也可能不同。不同的针和替换之间不会发生重叠。new Regex(“b”)
不是正则表达式。@Cobra\u Fast Edited,如果您想要相同的结果,您只需先反向检查,检查b
,然后将所有b
替换为c
,然后检查a
并替换为ab
,这样ab
中的b
就不会被替换。你太接近我在答案中的示例了。顺序、字符串和替换可以有很大的不同。哦,我想我知道,明白了,你不想用另一个正则表达式替换任何匹配项,对吗?我会循环遍历,找到正则表达式的匹配项,将每个“匹配对”推到列表中,然后循环遍历
using System;
using System.IO;
using System.Text.RegularExpressions;
class MultiRegex {
static String Replace(String text, Regex[] expressions,
String[] replacements, int start=0)
{
// Try matching each regex; save the first match
Match firstMatch = null;
int firstMatchingExpressionIndex = -1;
for (int i = 0; i < expressions.Length; i++) {
Regex r = expressions[i];
Match m = r.Match(text, start);
if (m.Success
&& (firstMatch == null || m.Index < firstMatch.Index))
{
firstMatch = m;
firstMatchingExpressionIndex = i;
}
}
if (firstMatch == null) {
/* No matches anywhere */
return text;
}
// Replace text, then recurse
String newText = text.Substring(0, firstMatch.Index)
+ replacements[firstMatchingExpressionIndex]
+ text.Substring(firstMatch.Index + firstMatch.Length);
return Replace(newText, expressions, replacements,
start + replacements[firstMatchingExpressionIndex].Length);
}
public static void Main() {
Regex[] expressions = new Regex[]
{
new Regex("a"), //replaced by ab
new Regex("b") //replaced by c
};
string[] replacements = new string[]
{
"ab",
"c"
};
string original = "a b c";
Console.WriteLine(
Replace(original, expressions, replacements));
// Should be "baz foo bar"
Console.WriteLine(Replace("foo bar baz",
new Regex[] { new Regex("bar"), new Regex("baz"),
new Regex("foo") },
new String[] { "foo", "bar", "baz" }));
}
}
ab c c
baz foo bar
ab
%1b
%1%2
b%2
ba