使用RegEx.Replace将匹配替换为两个表达式中的捕获

时间:2011-03-02 21:08:11

标签: .net regex replace

我正在寻找一种方法来使用RegEx从两个单独的表达式中捕获组,并使用它们进行搜索,并在单个字符串中替换两个替换之间共享的捕获。

例如:

string input_a = "abc-def-ghi";
string input_b = "123-4567-89";

string pattern_a = "(?<first>def)";  // captures 'def' from input_a and 
                                     // names the capture as 'first'
string pattern_b = "(?<second>456)"; // captures '456' from input_b and
                                     // names the capture as 'second'

string translation_a = "A=${first}${second}"; // replacement strings use the named
string translation_b = "B=${second}${first}"; // captures from both RegExs

// I want the results of the replace to give:

Console.Write("Result A: abc-A=def456-ghi"); // result of regex search and replace
                                             // matches on 'def' and replaces this
                                             // with 'A=' followed by 'def' from the 
                                             // first expression and '456' from the
                                             // second expression

Console.Write("Result B: 123-B=456def-789"); // same thing again but the other way
                                             // around

我的输入/模式/翻译在运行时都是未知的,因为它们是用户可配置的并存储在数据库中。

有人能建议一个优雅的方式来做到这一点吗?

更新

为了给我的问题提供更多背景,这是一个真实的例子。我在处理来电的电信系统中使用它。当呼叫进来时,它们有两条信息:拨打的号码(在DDI处已知)和主叫号码(称为CLI)。

我正在创建的系统需要使用存储在数据库中的“规则”列表以非常动态的可配置方式路由数字,这些规则实际上是一组正则表达式。规则需要通过GUI更新,因此不能对任何内容进行硬编码。

系统的这一部分对来电进行了一种预路由转换。一些例子包括(这都是虚构的数据):

DDI              CLI
800123400        01373000001
4150800123401    01373000002
123402077000000  01373000003

我需要调用他们的DDI和CLI翻译来“走出另一边”。我的数据库包含:DDISearchPattern,DDITranslation,CLISearchPattern,CLITranslation。

我的第一个简单规则是:

DDISearchPattern = "^0?(?<ddi>\d{9})$"
DDITranslation   = "0${ddi}"
CLISearchPattern = "^0?(?<cli>\d{9})$"
CLITranslation   = "0${cli}"

有时呼叫会使系统错过前导零。此规则将重新添加。

下一条规则是删除415前缀。

DDISearchPattern = "^4150?(?<ddi>\d{9})$"
DDITranslation   = "0${ddi}"
CLISearchPattern = "^0?(?<cli>\d{9})$"
CLITranslation   = "0${cli}"

但这是我的问题。在最后一个例子中(DDI = 123402077000000)我想将CLI附加到DDI的末尾,所以我想最终得到12340207700000001373000001。

我希望能够做到这一点:

DDISearchPattern = "^12340?(?<ddi?\d{9})$"
DDITranslation   = "12340${ddi}${cli}"
CLISearchPattern = "^0?(?<cli>\d{9})$"
CLITranslation   = "0${cli}"

但不幸的是,${cli}捕获组是CLI正则表达式的一部分,而不是DDI正则表达式。如何使用其他正则表达式中捕获的组“加载”一个正则表达式,以便我可以使用两者的捕获进行替换?

我找到了一种方法,但是使用正则表达式替换@'\$\{cli\}'是一种非常混乱的方式。我真的想找到一种更简单的方法。

1 个答案:

答案 0 :(得分:0)

修改
好的,我明白你要做什么了。让我们说引擎不会在正则表达式之间保留分组值。

这将实际上是每个表达式的两次传递。第一次通过捕获第一次/第二次,第二次通过,用第1次传输中保存的第一/第二个值进行替换。

string pattern_a = "(?<first>def)";
string pattern_b = "(?<second>456)";

//在input_a上运行与pattern_a的匹配 string res_first = "${first}";

//在input_b上运行与pattern_b的匹配 string res_second = "${second}";

//使用res_first res_second
在input_a上运行替换pattern_a //使用res_first res_second在input_b上运行替换pattern_b 等等......

结束

如果我理解正确的话。
我还不知道.net。但通常情况下,正则表达式结果在下一个正则表达式之前有效,之后的结果现在无效。

但如果没有,那么你需要一些更独立的名字。

string input_a = "abc-def-ghi";
string input_b = "123-4567-89";

string pattern_a = "^(?<apre>.*)(?<first>def)(?<apost>.*)$";
string pattern_b = "^(?<bpre>.*)(?<second>456)(?<bpost>.*)$";

string translation_a = "${apre}A=${first}${second}${apost}";
string translation_b = "${bpre}B=${second}${first}${bpost}";

如果无效,则需要在首次运行后保存结果。这样的事情(警告,我不熟悉.net中的连锁):

string input_a = "abc-def-ghi";
string input_b = "123-4567-89";

string pattern_a = "^(?<pre>.*)(?<first>def)(?<post>.*)$";
string pattern_b = "^(?<pre>.*)(?<second>456)(?<post>.*)$";

// Do the regex for input_a
// Save off the capture vars here..

string A_pre   =  "${pre}"; 
string A_first =  "${first}"; 
string A_post  =  "${post}"; 

// Do the regex for input_b

string translation_a = A_pre + "A=" + A_first + "${second}";
string translation_b = "${pre}B=${second}" + A_first + "${post}";