Eliminar texto entre los delimitadores en una cadena (utilizando una expresión regular?)

Considere el requisito de encontrar un par de caracteres coincidentes y eliminar cualquier carácter entre ellos, así como esos caracteres / delimitadores.

Aquí están los conjuntos de delimitadores:

[] square brackets () parentheses "" double quotes '' single quotes 

Aquí hay algunos ejemplos de cadenas que deberían coincidir:

  Given: Results In: ------------------------------------------- Hello "some" World Hello World Give [Me Some] Purple Give Purple Have Fifteen (Lunch Today) Have Fifteen Have 'a good'day Have day 

Y algunos ejemplos de cadenas que no deberían coincidir:

  Does Not Match: ------------------ Hello "world Brown]co[w Cheese'factory 

Si la cadena dada no contiene un conjunto coincidente de delimitadores, no se modifica. La cadena de entrada puede tener muchos pares coincidentes de delimitadores. Si un conjunto de 2 delimitadores se superponen (es decir, he[llo "worl]d" ), sería un caso límite que podemos ignorar aquí.

El algoritmo se vería así:

 string myInput = "Give [Me Some] Purple (And More) Elephants"; string pattern; //some pattern string output = Regex.Replace(myInput, pattern, string.Empty); 

Pregunta: ¿Cómo lograrías esto con C #? Me estoy inclinando hacia una expresión regular.

Bono: ¿Hay formas fáciles de emparejar esos delimitadores de inicio y final en constantes o en una lista de algún tipo? La solución que estoy buscando sería fácil de cambiar los delimitadores en caso de que los analistas de negocios obtengan nuevos conjuntos de delimitadores.

La expresión regular simple sería:

 string input = "Give [Me Some] Purple (And More) Elephants"; string regex = "(\\[.*\\])|(\".*\")|('.*')|(\\(.*\\))"; string output = Regex.Replace(input, regex, ""); 

En cuanto a hacerlo de forma personalizada donde quiera construir la expresión regular, solo necesitaría construir las partes:

 ('.*') // example of the single quote check 

Luego, haga que cada parte de la expresión regular se concatene con un OR (the | in regex) como en mi ejemplo original. Una vez que haya creado su cadena de expresiones regulares, solo ejecútela una vez. La clave es obtener la expresión regular en una sola comprobación porque realizar muchas coincidencias de expresiones regulares en un elemento y luego iterar a través de muchos elementos probablemente verá una disminución significativa en el rendimiento.

En mi primer ejemplo que tomaría el lugar de la siguiente línea:

 string input = "Give [Me Some] Purple (And More) Elephants"; string regex = "Your built up regex here"; string sOutput = Regex.Replace(input, regex, ""); 

Estoy seguro de que alguien publicará una expresión cool linq para construir la expresión regular basada en una matriz de objetos delimitadores para que coincida o algo así.

Una manera simple sería hacer esto:

 string RemoveBetween(string s, char begin, char end) { Regex regex = new Regex(string.Format("\\{0}.*?\\{1}", begin, end)); return regex.Replace(s, string.Empty); } string s = "Give [Me Some] Purple (And More) \\Elephants/ and .hats^"; s = RemoveBetween(s, '(', ')'); s = RemoveBetween(s, '[', ']'); s = RemoveBetween(s, '\\', '/'); s = RemoveBetween(s, '.', '^'); 

Cambiar la statement de devolución a lo siguiente evitará espacios vacíos duplicados:

 return new Regex(" +").Replace(regex.Replace(s, string.Empty), " "); 

El resultado final de esto sería:

 "Give Purple and " 

Descargo : una sola expresión regular probablemente sea más rápida que esto.

Tengo que agregar el viejo refrán, “Tienes un problema y quieres usar expresiones regulares. Ahora tienes dos problemas”.

He sacado una expresión regular rápida que con suerte te ayudará en la dirección que estás buscando:

 [.]*(\(|\[|\"|').*(\]|\)|\"|')[.]* 

Los paréntesis, corchetes, comillas dobles se escapan mientras que la comilla simple se puede dejar en paz.

Para poner la expresión anterior en inglés, estoy permitiendo cualquier cantidad de caracteres antes y cualquier número posterior, haciendo coincidir la expresión entre los delimitadores coincidentes.

La frase del delimitador abierto es (\(|\[|\"|') Esto tiene una frase de cierre coincidente. Para hacerlo un poco más extensible en el futuro, puede eliminar los delimitadores reales y contenerlos en un archivo de configuración, base de datos o donde sea que puedas elegir

Sobre la base de la expresión regular de Bryan Menard , hice un método de extensión que también funcionará para reemplazos nesteds como “[Test 1 [[Test2] Test3]] Hello World”:

  ///  /// Method used to remove the characters betweeen certain letters in a string. ///  ///  ///  ///  ///  public static string RemoveFragmentsBetween(this string rawString, char enter, char exit) { if (rawString.Contains(enter) && rawString.Contains(exit)) { int substringStartIndex = rawString.IndexOf(enter) + 1; int substringLength = rawString.LastIndexOf(exit) - substringStartIndex; if (substringLength > 0 && substringStartIndex > 0) { string substring = rawString.Substring(substringStartIndex, substringLength).RemoveFragmentsBetween(enter, exit); if (substring.Length != substringLength) // This would mean that letters have been removed { rawString = rawString.Remove(substringStartIndex, substringLength).Insert(substringStartIndex, substring).Trim(); } } //Source: https://stackoverflow.com/a/1359521/3407324 Regex regex = new Regex(String.Format("\\{0}.*?\\{1}", enter, exit)); return new Regex(" +").Replace(regex.Replace(rawString, string.Empty), " ").Trim(); // Removing duplicate and tailing/leading spaces } else { return rawString; } } 

El uso de este método en el caso sugerido se vería así:

 string testString = "[Test 1 [[Test2] Test3]] Hello World"; testString.RemoveFragmentsBetween('[',']'); 

Devolviendo la cadena “Hello World”.

Use la siguiente Regex

 (\{\S*\}) 

Lo que hace esta expresión regular es que reemplaza cualquier aparición de {palabra} con la palabra modificada con la que desea reemplazarla.

Algunos ejemplos de código c #:

  static readonly Regex re = new Regex(@"(\{\S*\})", RegexOptions.Compiled); ///  /// Pass text and collection of key/value pairs. The text placeholders will be substituted with the collection values. ///  /// Text that containes placeholders such as {fullname} /// a collection of key values pairs. Pass fullname and the value Sarah. /// DO NOT PASS keys with curly brackets {} in the collection. /// Substituted Text public static string ReplaceMatch(this string text, StringDictionary fields) { return re.Replace(text, match => fields[match.Groups[1].Value]); } 

En una oración como

Regex Hero es un probador de expresiones {Online { Silverlight } regular} en tiempo real.

Reemplazará solo { Silverlight } y no comenzará desde el primer soporte {paréntesis hasta el último}.