2009-08-31 20 views
40

Considere la necesidad de encontrar un par de caracteres coincidentes, y eliminar los caracteres entre ellos, , así como esos caracteres/delimitadores.Eliminar delimitadores intermedios de texto en una cadena (utilizando una expresión regular?)

Éstos son los juegos de delimitadores:

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

Aquí están algunos ejemplos de cadenas que deben 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 deben 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 marginal que podemos ignorar aquí.

El algoritmo sería algo como esto:

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

Pregunta: ¿Cómo lograrlo con C#? Me estoy inclinando hacia una expresión regular.

Bonificación: ¿Hay formas fáciles de combinar 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.

Respuesta

35

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 una manera personalizada, en la que quiere construir la expresión regular que sólo se necesitaría para construir las partes:

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

luego tener cada parte de expresión regular individual concatenada con un OR (el | en expresión regular) 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 va a publicar una expresión LINQ fresco para construir la expresión regular sobre la base de una matriz de objetos delimitadores para que coincida o algo .

+2

Esto funcionaría ahora (lo más probable) esperado para "Dar [Me Some] Purple (Y más) [Big] Elephants". Esto se puede resolver usando '. *?' en lugar de '. *' en la expresión proporcionada anteriormente. – mayu

9

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

Yo he llegado con una expresión regular rápida que esperamos le ayude en la dirección que busca:

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

el paréntesis, corchetes, comillas dobles se escaparon, mientras que la comilla simple es capaz de ser dejado solo.

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

La frase delimitadora abierta es (\(|\[|\"|') Tiene una frase de cierre coincidente. Para hacer esto 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 pueda elegir.

+0

+1 regex parece hacer lo que necesita. Solo una expresión regular simple. Se necesita reemplazar para redondearlo. – James

+5

golpe para el "... Ahora tiene dos problemas.", LOL –

34

Una forma sencilla sería la de 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, '.', '^'); 

Cambio de la instrucción de retorno a la siguiente evitará vacíos duplicados:

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

El resultado final de esto sería:

"Give Purple and " 

Disclamer: Una sola expresión regular haría probablemente más rápido que esto.

+3

El OP no incluyó ninguna mención de 'y sombreros'. "Dame púrpura y más elefantes" fue lo que OP solicitó explícitamente. ¿Por qué has torcido sus palabras y añadido sombreros a la ecuación? –

+1

+1. Me encontré de nuevo en este hilo y no me di cuenta de que había publicado el comentario anterior. Pobre intento de humor. Gracias por tu respuesta. –

+0

¿Por qué sombreros? Supongo que es mi pobre intento de humor;). Me alegra ver que esto todavía es útil. –

0

Usar la siguiente expresión regular

(\{\S*\}) 

expresiones regulares Lo que esto hace es que reemplaza cualquier apariciones de la palabra {} con el modifiedWord que desea sustituir.

Parte de la muestra de código C#:

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

En una oración como

expresión regular es un héroe en tiempo real en línea {{Silverlight}} Expresión regular probador.

Sustituirá solamente {Silverlight} y no a partir del primero {soporte a la última} soporte.

2

Sobre la base de Bryan Menard's regular expression, hice un método de extensión que también funcionará para reemplazos anidados como "[Test 1 [[Prueba2] Test3]] Hello World":

/// <summary> 
    /// Method used to remove the characters betweeen certain letters in a string. 
    /// </summary> 
    /// <param name="rawString"></param> 
    /// <param name="enter"></param> 
    /// <param name="exit"></param> 
    /// <returns></returns> 
    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 ven así:

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

Volviendo a la cadena "Hello World".

+0

Oro! ¡gracias! –

Cuestiones relacionadas