Использование RegEx.Replace для замены совпадений захватами из двух выражений - PullRequest
0 голосов
/ 03 марта 2011

Я ищу способ использования 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

Все мои входные данные / шаблоны / переводы не известны во время выполнения, поскольку они настраиваются пользователем и хранятся в базе данных.

Кто-нибудь может предложить аккуратный элегантный способ сделать это?

UPDATE

Чтобы дать немного больше контекста моему вопросу, вот пример из реальной жизни. Я использую это в телекоммуникационной системе, которая обрабатывает входящие звонки. Когда поступают вызовы, у них есть две части информации: набранный номер (известный в DDI) и вызывающий номер (известный как CLI).

Система, которую я создаю, должна маршрутизировать числа динамически настраиваемым способом, используя список «правил», хранящихся в базе данных, которые на самом деле представляют собой набор регулярных выражений. Правила должны быть обновлены через графический интерфейс, так что ничто не может быть жестко запрограммировано.

Эта часть системы выполняет своего рода предварительную маршрутизацию трансляции входящих вызовов. Вот некоторые примеры (это все вымышленные данные):

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 голосов
/ 03 марта 2011

edit
Хорошо, я вижу, что вы пытаетесь сделать.Допустим, движок не сохраняет значения группировки между регулярными выражениями.

На самом деле это займет 2 прохода каждого выражения.Первый проход для захвата первого / второго, второй проход для подстановки с сохраненными первыми / вторыми значениями из прохода 1.

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

// запустить сопоставление с pattern_a для input_a
string res_first = "${first}";

// запустить сопоставление с pattern_b для input_b
string res_second = "${second}";

// запустить замену pattern_a для input_a, используя res_first res_second
// запустить замену pattern_b для input_b, используя res_first res_second
и т. д., ...

end

Если я вас правильно понимаю ..
Я еще не знаю .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}";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...