c# - sharp - Reemplaza solo algunos grupos con Regex
replace c# expresiones regulares (6)
Supongamos que tengo la siguiente expresión regular:
-(/d+)-
y quiero reemplazar, usando C #, el Grupo 1 (/d+)
con AA
, para obtener:
-AA-
Ahora lo estoy reemplazando usando:
var text = "example-123-example";
var pattern = @"-(/d+)-";
var replaced = Regex.Replace(text, pattern, "-AA-");
Pero realmente no me gusta esto, porque si cambio el patrón para que coincida con _(/d+)_
lugar, tendré que cambiar la cadena de reemplazo por _AA_
también, y esto va en contra del principio DRY.
Estoy buscando algo como:
Mantenga el texto coincidente exactamente como está, pero cambie el Grupo 1 por this text
y el Grupo 2 por another text
...
Editar:
Eso fue solo un ejemplo. Solo busco una manera genérica de hacer lo que dije arriba.
Debería funcionar para:
anything(/d+)more_text
y cualquier patrón que puedas imaginar.
Todo lo que quiero hacer es reemplazar solo grupos, y mantener el resto del partido.
Aquí hay otra opción de limpieza agradable que no requiere cambiar su patrón.
var text = "example-123-example";
var pattern = @"-(/d+)-";
var replaced = Regex.Replace(text, pattern, (_match) =>
{
Group group = _match.Groups[1];
string replace = "AA";
return String.Format("{0}{1}{2}", _match.Value.Substring(0, group.Index - _match.Index), replace, _match.Value.Substring(group.Index - _match.Index + group.Length));
});
Puedes hacer esto usando lookahead y lookbehind :
var pattern = @"(?<=-)/d+(?=-)";
var replaced = Regex.Replace(text, pattern, "AA");
Si no desea cambiar su patrón, puede usar las propiedades Índice de grupo y Longitud de un grupo coincidente.
var text = "example-123-example";
var pattern = @"-(/d+)-";
var regex = new RegEx(pattern);
var match = regex.Match(text);
var firstPart = text.Substring(0,match.Groups[1].Index);
var secondPart = text.Substring(match.Groups[1].Index + match.Groups[1].Length);
var fullReplace = firstPart + "AA" + secondPart;
También tuve necesidad de esto y creé el siguiente método de extensión para él:
public static class RegexExtensions
{
public static string ReplaceGroup(
this Regex regex, string input, string groupName, string replacement)
{
return regex.Replace(
input,
m =>
{
var group = m.Groups[groupName];
var sb = new StringBuilder();
var previousCaptureEnd = 0;
foreach (var capture in group.Captures.Cast<Capture>())
{
var currentCaptureEnd =
capture.Index + capture.Length - m.Index;
var currentCaptureLength =
capture.Index - m.Index - previousCaptureEnd;
sb.Append(
m.Value.Substring(
previousCaptureEnd, currentCaptureLength));
sb.Append(replacement);
previousCaptureEnd = currentCaptureEnd;
}
sb.Append(m.Value.Substring(previousCaptureEnd));
return sb.ToString();
});
}
}
Uso:
var input = @"[assembly: AssemblyFileVersion(""2.0.3.0"")][assembly: AssemblyFileVersion(""2.0.3.0"")]";
var regex = new Regex(@"AssemblyFileVersion/(""(?<version>(/d+/.?){4})""/)");
var result = regex.ReplaceGroup(input , "version", "1.2.3");
Resultado:
[assembly: AssemblyFileVersion("1.2.3")][assembly: AssemblyFileVersion("1.2.3")]
Una buena idea podría ser encapsular todo dentro de los grupos, sin importar si es necesario identificarlos o no. De esa forma puedes usarlos en tu cadena de reemplazo. Por ejemplo:
var pattern = @"(-)(/d+)(-)";
var replaced = Regex.Replace(text, pattern, "$1AA$3");
o usando un MatchEvaluator:
var replaced = Regex.Replace(text, pattern, m => m.Groups[1].Value + "AA" + m.Groups[3].Value);
Otra forma, un poco desordenada, podría ser utilizar un lookbehind / lookahead:
(?<=-)(/d+)(?=-)
siga la codificación a continuación para obtener el reemplazo de grupo por separado.
new_bib = Regex.Replace(new_bib, @"(?s)(//bibitem/[[^/]]+/]/{" + pat4 + @"/})[/s/n/v]*([///{/}a-zA-Z/./s/,/;///#///$///%///&/*/@///!///^+/-///=///~///:///" + dblqt + @"///;///`///']{20,70})", delegate(Match mts)
{
var fg = mts.Groups[0].Value.ToString();
var fs = mts.Groups[1].Value.ToString();
var fss = mts.Groups[2].Value.ToString();
fss = Regex.Replace(fss, @"[///{/}///#///$///%///&/*/@///!///^+/-///=///~///:///" + dblqt + @"///;///`///']+", "");
return "<augroup>" + fss + "</augroup>" + fs;
}, RegexOptions.IgnoreCase);