当我们不使用通配符时,我找到了答案。所以问题是 - 如何通过正则表达式执行多次替换。此代码显示了我想要做的事情
internal class Program
{
private static void Main(string[] args)
{
var rules = new Dictionary<string, string>
{
{@"F\S+", "Replace 1"},
{@"\S+z", "Replace 2"},
};
string s = "Foo bar baz";
string result = ProcessText(s, rules);
Console.WriteLine(result);
}
private static string ProcessText(string input, Dictionary<string, string> rules)
{
string[] patterns = rules.Keys.ToArray();
string pattern = string.Join("|", patterns);
return Regex.Replace(input, pattern, match =>
{
int index = GetMatchIndex(match);
return rules[patterns[index]];
});
}
private static int GetMatchIndex(Match match)
{
int i = 0;
foreach (Match g in match.Groups)
{
if (g.Success)
return i;
i++;
}
throw new Exception("Never throws");
}
}
但match.Groups.Count
始终为1。
我正在寻找最快的选择。也许,它不应该使用正则表达式。
答案 0 :(得分:1)
我不明白为什么你要连接模式然后在数组中进行如此多的搜索。
你不能像这样单独应用每个模式吗?
var rules = new Dictionary<string, string>
{
{@"F\S+", "Replace 1"},
{@"\S+z", "Replace 2"},
};
string s = "Foo bar baz";
var result = rules.Aggregate(s, (seed, rule) => Regex.Replace(seed, rule.Key, m => rule.Value));
修改强>
您的match.Groups.Count
始终是一个,因为您的匹配中没有定义任何组,而值是MSDN中描述的整个匹配字符串。换句话说,您的GetMatchIndex
方法无效。
您可以尝试将模式转换为命名组,如下所示:
var patterns = rules.Select((kvp, index) => new
{
Key = String.Format("(?<{0}>{1})", index, kvp.Key),
Value = kvp.Value
};
拥有此数组,在GetMatchIndex
方法中,您只需将组名称解析为匹配模式的索引:
private static int GetMatchIndex(Regex regex, Match match)
{
foreach(var name in regex.GetGroupNames())
{
var group = match.Groups[name];
if(group.Success)
return int.Parse(name); //group name is a number
}
return -1;
}
现在,您可以像这样使用它:
var pattern = String.Join("|", patterns.Select(x => x.Key));
var regex = new Regex(pattern);
return regex.Replace(input, pattern, m =>
{
var index = GetMatchIndex(regex, m);
return patterns[index].Value;
});
答案 1 :(得分:0)
使它(可能是方式)更快提取
var keyArray = rules.Keys.ToArray()
在您使用它之前:
return Regex.Replace(input, pattern, match =>
{
int index = GetMatchIndex(match);
return rules[keyArray[index]];
});