2013-03-05 4 views
4

мне нужно взять эту строку:Regex заменить символ с индексом матча

book_id = ? and author_id = ? and publisher_id = ? 

и превратить его в эту строку:

book_id = @p1 and author_id = @p2 and publisher_id = @p3 

, используя этот код:

Regex.Replace(input, @"(\?)", "@p **(index of group)**"); 

Что это шаблон замены, чтобы дать мне индекс группы?

+0

Однострочники легко - просто выполнить ** Заменить (» \ n "," ") ** в исходном коде –

+0

Очень симпатичный ответ; p – schmij

+0

Могу ли я решить его с помощью регулярного выражения в шаблоне замены в третьем параметре? – schmij

ответ

2

Вы можете использовать Regex.Replace method, который принимает MatchEvaluator, наряду с переменной счетчика:

string input = "book_id = ? and author_id = ? and publisher_id = ?"; 
string pattern = @"\?"; 
int count = 1; 
string result = Regex.Replace(input, pattern, m => "@p" + count++); 

m => часть является MatchEvaluator. В этом случае нет необходимости использовать Match (то есть m); мы просто хотим вернуть конкатенированный результат и увеличить счетчик.

+0

Мы получаем теплый ответ с этим ответом. Однако мне нужно будет содержать расчет индекса в re шаблон размещения. – schmij

+0

@schmij вы можете объяснить, что вы подразумеваете под индексированием группы? Мой подход дает результат, похожий на ваш вопрос. Если вам нужен индекс появления '?' Во входе, вы можете использовать 'm.Index' в лямбда вместо переменной' count'. Или, если шаблон использует группу, '@" (\?) "', Вы можете использовать 'm.Groups [1] .Index'. Я не думаю, что это соответствует вашему запросу. Возможно, еще один пример выхода поможет прояснить, что вам нужно. –

+0

Я ищу шаблон замены, специфичный для регулярного выражения, для создания индекса соответствующей группы. – schmij

0

Непроверенные:

int n, i=1; while((n=input.IndexOf("?")) != -1) { input = input.Substring(0,n-1) + "@p" + (++i) + input.Substring(n+1); } 

Длинноватый линия, но не полностью необоснованным.

+0

Да, это одна строка .. но я не совсем уверен, что это то, к чему стремился ОП. –

0

Если вы хотите использовать однострочное решение, вы можете сделать что-то вроде этого, но может быть медленным для больших строк, поскольку он должен найти счетчик «?». для каждого матча

var result = Regex.Replace(input, @"\?", m => "@p" + input.Take(m.Index).Count(c => c == '?')); 

возвратов "book_id = @p0 and author_id = @p1 and publisher_id = @p2"

Это единственный способ, которым я могу видеть, чтобы получить indext без объявления внешней переменной.

+0

Я обновил свой ответ, используя однострочное решение –

0

Я пишу проект, чтобы проверить другие ответы и свои собственные. Вы можете получить его here.
Заключение:
- решение linq является самым быстрым.
- Реджикс-решение является самым элегантным.
- Мое решение с StringBuilder не плохо, но это не самый быстрый и не самый элегантный :(

Вот мое решение:

var count = 1; 
var sb = new StringBuilder(input); 
for (int i = 0; i < sb.Length; i++) 
{ 
    if (sb[j] == '?') 
    { 
     sb.Remove(i, 1); 
     sb.Insert(i, "@p" + (count++)); 
     i += 3; 
    } 
} 
result = sb.ToString(); 
Смежные вопросы