正则表达式替换多个组

baa*_*mon 21 .net c# regex replace

我想使用正则表达式替换具有相应替换字符串的多个组.

替换表:

  • & - > __amp
  • # - > __hsh
  • 1 - > 5
  • 5 - > 6

例如,对于以下输入字符串

a1asda&FJ#ahdk5adfls

相应的输出字符串是

a5asda__ampfj__hshahdk6adfls

有没有办法做到这一点?

Jam*_*iec 41

给定一个定义替换的字典:

IDictionary<string,string> map = new Dictionary<string,string>()
        {
           {"&","__amp"},
           {"#","__hsh"},
           {"1","5"},
           {"5","6"},
        };
Run Code Online (Sandbox Code Playgroud)

您可以使用它来构建正则表达式,并为每个匹配形成替换:

var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Run Code Online (Sandbox Code Playgroud)

实例:http://rextester.com/rundotnet?code = ADDN57626

这使用Replace(docs)重载,允许您为替换指定lambda表达式.


在评论中已经指出,具有正则表达式语法的查找模式将无法按预期工作.这可以通过Regex.Escape对上面的代码使用和稍微更改来克服:

var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys.Select(k => Regex.Escape(k))));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Run Code Online (Sandbox Code Playgroud)

  • 但是,你仍然应该逃避字符串.如果要替换的一个令牌是`$`怎么办? (3认同)

p.c*_*ell 6

怎么用string.Replace()

string foo = "a1asda&fj#ahdk5adfls"; 

string bar = foo.Replace("&","__amp")
                .Replace("#","__hsh")
                .Replace("5", "6")
                .Replace("1", "5");
Run Code Online (Sandbox Code Playgroud)

  • 这只能起作用,因为你已经重新排序了5 - > 6和1 - > 5,实际上你可能有1 - > 5和5 - > 1并且它不起作用. (5认同)
  • 哎呀,我认为这比我的要好,但是OP要求使用正则表达式,现在OP存在两个问题:) (2认同)

Ray*_*Ray 5

与Jamiec的答案类似,但这允许您使用与文本不完全匹配的正则表达式,例如\.不能与Jamiec的答案一起使用,因为您无法在字典中查找匹配项。

该解决方案依赖于创建组,查找匹配的组,然后查找替换值。它更复杂,但更灵活。

首先将地图设为KeyValuePairs列表

var map = new List<KeyValuePair<string, string>>();           
map.Add(new KeyValuePair<string, string>("\.", "dot"));
Run Code Online (Sandbox Code Playgroud)

然后像这样创建你的正则表达式:

string pattern = String.Join("|", map.Select(k => "(" + k.Key + ")"));
var regex = new Regex(pattern, RegexOptions.Compiled);
Run Code Online (Sandbox Code Playgroud)

然后匹配评估器变得有点复杂:

private static string Evaluator(List<KeyValuePair<string, string>> map, Match match)
{            
    for (int i = 0; i < match.Groups.Count; i++)
    {
        var group = match.Groups[i];
        if (group.Success)
        {
            return map[i].Value;
        }
    }

    //shouldn't happen
    throw new ArgumentException("Match found that doesn't have any successful groups");
}
Run Code Online (Sandbox Code Playgroud)

然后像这样调用正则表达式替换:

var newString = regex.Replace(text, m => Evaluator(map, m))
Run Code Online (Sandbox Code Playgroud)


Cos*_*tas 5

给定其他答案中的字典,您可以使用“聚合”将字典中的每个模式映射到替换。这将为您提供比其他答案更大的灵活性,因为您可以为每个模式使用不同的正则表达式选项。

例如,以下代码将“罗马化”希腊文本(https://en.wikipedia.org/w/index.php?title=Romanization_of_Greek§ion=3#Modern_Greek , Standard/UN):

var map = new Dictionary<string,string>() {
    {"?[??](?=[??????????????????????????])", "av"}, {"?[??]", "af"}, {"?[??]", "aï"}, {"?[??]", "ai"}, {"[??]", "a"},
    {"?", "v"}, {"?(?=[???])", "n"}, {"?", "g"}, {"?", "d"},
    {"?[??](?=[??????????????????????????])", "ev"}, {"?[??]", "ef"}, {"??", "ei"}, {"[??]", "e"}, {"?", "z"},
    {"?[??](?=[??????????????????????????])", "iv"}, {"?[??]", "if"}, {"[????]", "i"}, {"[??]", "ï"},
    {"?", "th"}, {"?", "k"}, {"?", "l"}, {"\\b??|??\\b", "b"}, {"??", "mb"}, {"?", "m"}, {"?", "n"},
    {"?[??]", "oi"}, {"?[??]", "ou"}, {"[????]", "o"}, {"?", "x"}, {"?", "p"}, {"?", "r"},
    {"[??]", "s"}, {"?", "t"}, {"[????]", "y"}, {"?", "f"}, {"?", "ch"}, {"?", "ps"}
};

var input = "? ????????? ?????????? ???????? ??? ?? ???????? ????? ?? ????????."; 
map.Aggregate(input, (i, m) => Regex.Replace(i, m.Key, m.Value, RegexOptions.IgnoreCase));
Run Code Online (Sandbox Code Playgroud)

返回(不修改“输入”变量:

"o kalymnios sfoungaras psythirise pos tha voutixei choris na distazei."
Run Code Online (Sandbox Code Playgroud)

你当然可以使用类似的东西:

foreach (var m in map) input = Regex.Replace(input, m.Key, m.Value, RegexOptions.IgnoreCase);
Run Code Online (Sandbox Code Playgroud)

这确实修改了“输入”变量。

您也可以添加它以提高性能:

var remap = new Dictionary<Regex, string>();
foreach (var m in map) remap.Add(new Regex(m.Key, RegexOptions.IgnoreCase | RegexOptions.Compiled), m.Value);
Run Code Online (Sandbox Code Playgroud)

缓存或使重映射字典静态化,然后使用:

remap.Aggregate(input, (i, m) => m.Key.Replace(i, m.Value));
Run Code Online (Sandbox Code Playgroud)