C# 用正则表达式替换正则表达式
考虑两个正则表达式:C# 用正则表达式替换正则表达式,c#,regex,C#,Regex,考虑两个正则表达式: var regex_A = "Main\.(.+)\.Value"; var regex_B = "M_(.+)_Sp"; 我希望能够使用regex_a作为输入替换字符串,使用regex_B作为替换字符串。但反过来也是如此。和不提供额外信息,如每个正则表达式的格式字符串 具体来说,我想从一个输入字符串创建一个替换的字符串。因此: var input_A = "Main.Rotating.Value"; var replaced_B = input_A.RegEx_Awes
var regex_A = "Main\.(.+)\.Value";
var regex_B = "M_(.+)_Sp";
我希望能够使用regex_a作为输入替换字符串,使用regex_B作为替换字符串。但反过来也是如此。和不提供额外信息,如每个正则表达式的格式字符串
具体来说,我想从一个输入字符串创建一个替换的字符串。因此:
var input_A = "Main.Rotating.Value";
var replaced_B = input_A.RegEx_Awesome_Replace(regex_A, regex_B);
Assert.AreEqual("M_Rotating_Sp", replaced_B);
这也应该反过来工作(这就是为什么我不能对regex_B使用简单的string.format)。因为我不想为每个正则表达式提供格式字符串(我很懒)
我不知道这是否存在,或者如何称呼它。谷歌搜索找到我所有其他类型的正则表达式替换。。。不是这个
更新:
所以基本上我需要一种将正则表达式转换为格式字符串的方法
var regex_A_format = Regex2Format(regex_A);
Assert.AreEqual("Main.$1.Value", regex_A_format);
及
那么RegEx_替换和/或Regex2Format函数应该是什么样子呢
更新2:
我想RegEx_Awesome_替换应该是这样的(使用下面答案中的一些代码):
这将使regex2格式成为一个悬而未决的问题 一个正则表达式没有定义的方法来引用在另一个正则表达式中找到的匹配项。正则表达式不是格式字符串 您可以做的是将格式字符串的
Tuple
s与其正则表达式一起使用。e、 g
var a = new Tuple<Regex,string>(new Regex(@"(?<=Main\.).+(?=\.Value)"), @"Main.{0}.Value")
var b = new Tuple<Regex,string>(new Regex(@"(?<=M_).+(?=_Sp)"), @"M_{0}_Sp")`
var a=new Tuple(new Regex(@)(?类似的东西可能会起作用
var replaced_B = Regex.Replace(input_A, @"Main\.(.+)\.Value", @"M_$1_Sp");
你在找这样的东西吗
public static class StringExtenstions
{
public static string RegExAwesomeReplace(this string inputString,string searchPattern,string replacePattern)
{
Match searchMatch = Regex.Match(inputString,searchPattern);
Match replaceMatch = Regex.Match(inputString, replacePattern);
if (!searchMatch.Success || !replaceMatch.Success)
{
return inputString;
}
return inputString.Replace(searchMatch.Value, replaceMatch.Value);
}
}
字符串扩展方法返回搜索模式和替换模式的替换值字符串
这就是你所说的:
input_A.RegEx_Awesome_Replace(regex_A, regex_B);
因为您已经将问题简化为需要将Regex
更改为字符串格式(实现Regex2Format
)我将把我的答案集中在这一部分。注意,我的答案是不完整的,因为它没有解决所有解析正则表达式捕获组的问题,但是它适用于简单的情况
首先需要的是一个与正则表达式捕获组匹配的正则表达式。存在一个与转义括号符号不匹配的反向查找。还有其他情况会破坏此正则表达式。例如,非捕获组、通配符、方括号之间的内容
private static readonly Regex CaptureGroupMatcher = new Regex(@"(?<!\\)\([^\)]+\)");
这个helper函数将模式字符串值写入输出,它当前写入除用于转义的\
字符以外的所有内容
static void AppendPart(string pattern, int previousEndIndex, int endIndex, StringBuilder targetBuilder)
{
for (int i = previousEndIndex; i < endIndex; i++)
{
char c = pattern[i];
if (c == '\\' && i < pattern.Length - 1 && pattern[i + 1] != '\\')
{
//backslash not followed by another backslash - it's an escape char
}
else
{
targetBuilder.Append(c);
}
}
}
static void AppendPart(字符串模式、int-previousEndIndex、int-endIndex、StringBuilder-targetBuilder)
{
for(int i=previousEndIndex;i
测试用例
static void Test()
{
var cases = new Dictionary<string, string>
{
{ @"Main\.(.+)\.Value", @"Main.{0}.Value" },
{ @"M_(.+)_Sp(.*)", "M_{0}_Sp{1}" },
{ @"M_\(.+)_Sp", @"M_(.+)_Sp" },
};
foreach (var kvp in cases)
{
if (PatternToStringFormat(kvp.Key) != kvp.Value)
{
Console.WriteLine("Test failed for {0} - expected {1} but got {2}", kvp.Key, kvp.Value, PatternToStringFormat(kvp.Key));
}
}
}
static void Test()
{
var cases=新字典
{
{@“Main\.(.+)\.Value”,@“Main.{0}.Value”},
{@“M_(+)Sp(.*)”,“M_{0}Sp{1}”,
{“M \(.+)_Sp“,@“M \(.+)_Sp”},
};
foreach(案例中的var kvp)
{
if(PatternToStringFormat(kvp.Key)!=kvp.Value)
{
WriteLine(“对{0}的测试失败-预期为{1},但得到{2}”)、kvp.Key、kvp.Value、PatternToStringFormat(kvp.Key));
}
}
}
总而言之,这里是用法:
private static string AwesomeRegexReplace(string input, string sourcePattern, string targetPattern)
{
var targetFormat = PatternToStringFormat(targetPattern);
return Regex.Replace(input, sourcePattern, match =>
{
var args = match.Groups.OfType<Group>().Skip(1).Select(g => g.Value).ToArray<object>();
return string.Format(targetFormat, args);
});
}
私有静态字符串AwesomeRegexReplace(字符串输入、字符串源模式、字符串目标模式)
{
var targetFormat=PatternToStringFormat(targetPattern);
返回Regex.Replace(输入,sourcePattern,match=>
{
var args=match.Groups.OfType().跳过(1).选择(g=>g.Value).ToArray();
返回string.Format(targetFormat,args);
});
}
我喜欢这个。但这不是我需要的。现在我仍然需要将正则表达式转换为格式字符串(如string.format)。可能您需要澄清您作为输入的内容。是您自己编写正则表达式,还是它们来自应用程序外部(例如,作为用户输入)?来自用户输入外部,来自配置文件。我补充说,我需要函数的代码。为了更清楚地说明我不想添加数据。但最终还是为了更简洁从配置的角度来看。它们真的需要正则表达式的所有功能吗?还是只需要在前缀和后缀之间捕获一些文本?我认为您需要细化有效表达式的确切组成部分。所有可用于正则表达式的分组都使您非常不清楚要替换的确切内容。另外,更酷/更简短的方法是o执行参数化的正则表达式替换。但这不是我需要的。我再次更改了问题,以更清楚地表明我不想为每个正则表达式提供/写入格式字符串。替换模式与输入字符串不兼容,它们是不同的格式。所以这不起作用。Regex2Format(replacePattern)是否有效返回字符串或其他替换模式?如果它返回格式化字符串,您希望字符串如何格式化?有关格式的信息在哪里?如果您希望格式在replacePattern
中,它看起来是什么样子?您是否已将需求缩小到可解决的问题?不,我不认为常规的exp解题真的可以解决任何现实生活中的问题。用更简单的方式定义这两个表达式更有意义。那么,这个问题应该是封闭的,因为没有正确的答案。
private static readonly Regex CaptureGroupMatcher = new Regex(@"(?<!\\)\([^\)]+\)");
static string Regex2Format(string pattern)
{
var targetBuilder = new StringBuilder();
int previousEndIndex = 0;
int formatIndex = 0;
foreach (Match match in CaptureGroupMatcher.Matches(pattern))
{
var group = match.Groups[0];
int endIndex = group.Index;
AppendPart(pattern, previousEndIndex, endIndex, targetBuilder);
targetBuilder.Append('{');
targetBuilder.Append(formatIndex++);
targetBuilder.Append('}');
previousEndIndex = group.Index + group.Length;
}
AppendPart(pattern, previousEndIndex, pattern.Length, targetBuilder);
return targetBuilder.ToString();
}
static void AppendPart(string pattern, int previousEndIndex, int endIndex, StringBuilder targetBuilder)
{
for (int i = previousEndIndex; i < endIndex; i++)
{
char c = pattern[i];
if (c == '\\' && i < pattern.Length - 1 && pattern[i + 1] != '\\')
{
//backslash not followed by another backslash - it's an escape char
}
else
{
targetBuilder.Append(c);
}
}
}
static void Test()
{
var cases = new Dictionary<string, string>
{
{ @"Main\.(.+)\.Value", @"Main.{0}.Value" },
{ @"M_(.+)_Sp(.*)", "M_{0}_Sp{1}" },
{ @"M_\(.+)_Sp", @"M_(.+)_Sp" },
};
foreach (var kvp in cases)
{
if (PatternToStringFormat(kvp.Key) != kvp.Value)
{
Console.WriteLine("Test failed for {0} - expected {1} but got {2}", kvp.Key, kvp.Value, PatternToStringFormat(kvp.Key));
}
}
}
private static string AwesomeRegexReplace(string input, string sourcePattern, string targetPattern)
{
var targetFormat = PatternToStringFormat(targetPattern);
return Regex.Replace(input, sourcePattern, match =>
{
var args = match.Groups.OfType<Group>().Skip(1).Select(g => g.Value).ToArray<object>();
return string.Format(targetFormat, args);
});
}