我想使用与string.Format相同的正则表达式。我会解释
我有:
string pattern = "^(?<PREFIX>abc_)(?<ID>[0-9])+(?<POSTFIX>_def)$";
string input = "abc_123_def";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
string replacement = "456";
Console.WriteLine(regex.Replace(input, string.Format("${{PREFIX}}{0}${{POSTFIX}}", replacement)));
这有效,但我必须为regex.Replace提供“输入”。我不要那个。我想使用模式进行匹配,但也使用与字符串格式相同的方式创建字符串,用值替换命名组“ID”。这可能吗?
我正在寻找类似的东西:
string pattern = "^(?<PREFIX>abc_)(?<ID>[0-9])+(?<POSTFIX>_def)$";
string result = ReplaceWithFormat(pattern, "ID", 999);
结果将包含“abc_999_def”。如何做到这一点?
答案 0 :(得分:15)
是的,有可能:
public static class RegexExtensions
{
public static string Replace(this string input, Regex regex, string groupName, string replacement)
{
return regex.Replace(input, m =>
{
return ReplaceNamedGroup(input, groupName, replacement, m);
});
}
private static string ReplaceNamedGroup(string input, string groupName, string replacement, Match m)
{
string capture = m.Value;
capture = capture.Remove(m.Groups[groupName].Index - m.Index, m.Groups[groupName].Length);
capture = capture.Insert(m.Groups[groupName].Index - m.Index, replacement);
return capture;
}
}
用法:
Regex regex = new Regex("^(?<PREFIX>abc_)(?<ID>[0-9]+)(?<POSTFIX>_def)$");
string oldValue = "abc_123_def";
var result = oldValue.Replace(regex, "ID", "456");
结果是:abc_456_def
答案 1 :(得分:12)
不,如果不提供输入,则无法使用正则表达式。它必须有一些工作,模式不能向结果添加任何数据,一切都必须来自输入或替换。
使用String.Format的Intead,你可以使用后面的一个看,并指望前面指定“abc_”和“_def”之间的部分,并替换它:
string result = Regex.Replace(input, @"(?<=abc_)\d+(?=_def)", "999");
答案 2 :(得分:5)
user1817787回答出现问题,我必须对ReplaceNamedGroup
函数进行如下修改。
private static string ReplaceNamedGroup(string input, string groupName, string replacement, Match m)
{
string capture = m.Value;
capture = capture.Remove(m.Groups[groupName].Index - m.Index, m.Groups[groupName].Length);
capture = capture.Insert(m.Groups[groupName].Index - m.Index, replacement);
return capture;
}
答案 3 :(得分:1)
@ user1817787的原始方法的另一个编辑版本,这个支持命名组的多个实例(还包括对@Justin发布的类似修复(使用{match.Index返回结果, match.Length}而不是{0,input.Length})):
public static string ReplaceNamedGroup(
string input, string groupName, string replacement, Match match)
{
var sb = new StringBuilder(input);
var matchStart = match.Index;
var matchLength = match.Length;
var captures = match.Groups[groupName].Captures.OfType<Capture>()
.OrderByDescending(c => c.Index);
foreach (var capt in captures)
{
if (capt == null)
continue;
matchLength += replacement.Length - capt.Length;
sb.Remove(capt.Index, capt.Length);
sb.Insert(capt.Index, replacement);
}
var end = matchStart + matchLength;
sb.Remove(end, sb.Length - end);
sb.Remove(0, matchStart);
return sb.ToString();
}
答案 4 :(得分:1)
我缩短了ReplaceNamedGroup,仍然支持多次捕获。
private static string ReplaceNamedGroup(string input, string groupName, string replacement, Match m)
{
string result = m.Value;
foreach (Capture cap in m.Groups[groupName]?.Captures)
{
result = result.Remove(cap.Index - m.Index, cap.Length);
result = result.Insert(cap.Index - m.Index, replacement);
}
return result;
}
答案 5 :(得分:0)
简单的解决方案是参考替换的匹配组。因此,前缀为$1
,后缀为$3
。
我还没有测试过下面的代码,但应该与我最近写的regEx
类似:
string pattern = "^(?<PREFIX>abc_)(?<ID>[0-9])+(?<POSTFIX>_def)$";
string input = "abc_123_def";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
string replacement = String.Format("$1{0}$3", "456");
Console.WriteLine(regex.Replace(input, string.Format("${{PREFIX}}{0}${{POSTFIX}}", replacement)));
答案 6 :(得分:0)
万一这对任何人都有帮助,我可以一次性替换多个命名的捕获组,从而增强了答案。
public static class RegexExtensions
{
public static string Replace(this string input, Regex regex, Dictionary<string, string> captureGroupReplacements)
{
string temp = input;
foreach (var key in captureGroupReplacements.Keys)
{
temp = regex.Replace(temp, m =>
{
return ReplaceNamedGroup(key, captureGroupReplacements[key], m);
});
}
return temp;
}
private static string ReplaceNamedGroup(string groupName, string replacement, Match m)
{
string capture = m.Value;
capture = capture.Remove(m.Groups[groupName].Index - m.Index, m.Groups[groupName].Length);
capture = capture.Insert(m.Groups[groupName].Index - m.Index, replacement);
return capture;
}
}
用法:
var regex = new Regex(@"C={BasePath:""(?<basePath>[^\""].*)"",ResultHeadersPath:""ResultHeaders"",CORS:(?<cors>true|false)");
content = content.Replace(regex, new Dictionary<string, string>
{
{ "basePath", "www.google.com" },
{ "cors", "false" }
};
为此,所有功劳应归功于user1817787。
答案 7 :(得分:-1)
您应该查看有关RegEx替换here
的文档我创建了这个来替换一个命名组。我不能在所有组名称上使用循环解决方案,因为我的情况并非所有表达式都被分组。
public static string ReplaceNamedGroup(this Regex regex, string input, string namedGroup, string value)
{
var replacement = Regex.Replace(regex.ToString(),
@"((?<GroupPrefix>\(\?)\<(?<GroupName>\w*)\>(?<Eval>.[^\)]+)(?<GroupPostfix>\)))",
@"${${GroupName}}").TrimStart('^').TrimEnd('$');
replacement = replacement.Replace("${" + namedGroup + "}", value);
return Regex.Replace(input, regex.ToString(), replacement);
}