2014-12-04 2 views
2

Если у меня есть изменяющееся регулярное выражение, которое может выглядеть как любой из следующих моделей:Как выполнить замену регулярного выражения только для одной группы имен?

(.{2})(?<somedigit>\d+)(.{5}) 
(?<somedigit>\d+)(.{7}) 
(.{1})(?<somedigit>\d+) 

, и я хочу, чтобы заменить somedigit группы захвата с любым числом, и оставить все остальное нетронутым, как бы я сделать это (скажем, на C# или Java)?

Например, у меня есть этот текст:

QB2-G456 

и я использую это регулярное выражение:

(.{2})(?<somedigit>\d+)(.{5}) 

, чтобы соответствовать его, и сказать, что я хочу, чтобы заменить somedigit с 35, для получения этого окончательного результата:

QB35-G456 

Я знаю, что могу использовать эту замену текст:

${1}35${2} 

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

Поскольку может присутствовать несколько чисел, я не могу просто заменить \ d +, поскольку я не знаю, находятся ли цифры в начале или конце или середине и имеются ли другие числа в тексте дальше.

В идеале я надеялся на что-то вроде:

new Regex("(.{2})(?<somedigit>\d+)(.{5})").ReplaceCaptureGroup("QB2-G456", "somedigit", "35") 

и есть все, что проходит через неизмененный кроме somedigit захвата группы, которая была заменена.

Я искал подобные проблемы и нашел решения только там, где регулярное выражение является фиксированным и известным, как уже объяснялось выше.

+0

Почему бы не превратить другие группы в не-захвата ('(: хххх)' в отличие от '(хххх)')? Тогда у вас есть только одна вещь для замены в любом случае? –

+0

Конечно, но как бы написать этот код? Мне нужно включить остальную часть текста, чтобы определить позицию группы захвата, которую я хочу заменить, но если я это сделаю, наверняка весь матч будет заменен? Может быть, пример с двумя лайнерами? – pwnell

+0

Вы должны пометить это с помощью языка, который вы используете. – jpmc26

ответ

1

Вот как вы можете это сделать в C#:

var str1 = "QB2-G456"; 
var rx1 = new Regex(@"(.{2})(?<somedigit>\d+)(.{5})"); 
var res = rx1.Replace(str1, m => m.Value.Replace(m.Groups["somedigit"].Value, "35")); 
// Result: QB35-G35456 

Это заменит все вхождения «somedigit» содержимое группы внутри строки (т.е. QB2-G2456 превратится в QB35-G35456). Чтобы обойти эту проблему, используйте Regex.Replace(input, regex, repl, numOfReplacements) или этот метод:

public string ReplaceOnceAtIndex(string text, string search, string replace, int index) 
{ 
    if (index < 0) 
     return text; 
    return text.Substring(0, index) + replace + text.Substring(index + search.Length); 
} 
// ... And thenin the caller ... 
var res2 = rx1.Replace(str1, m => 
ReplaceOnceAtIndex(m.Value, m.Groups["somedigit"].Value, "35", m.Groups["somedigit"].Index)); 
// Result: QB35-G2456