Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何独家更换?_C#_Regex_String_Replace - Fatal编程技术网

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