2009-02-16 29 views
62

Me gustaría utilizar el método .Net Regex.Split para dividir esta cadena de entrada en una matriz. Debe dividirse en espacios en blanco a menos que esté incluido en una cita.Expresión regular para dividir en espacios a menos que entre comillas

de entrada: aquí es "mi cadena"         que tiene "seis     partidos"

Resultados previstos:

  1. Aquí
  2. es
  3. mi cadena
  4. it
  5. tiene
  6.     seis partidos

¿Qué patrón necesito? ¿También necesito especificar alguna RegexOptions?

+0

es "un delimitador partido? Iow, no hola" mundo" Count durante 1 o 2 partidos? –

+0

Buena pregunta .. yo creo que sería –

Respuesta

62

No hay opciones requieren

Regex:

\w+|"[\w\s]*" 

C#:

Regex regex = new Regex(@"\w+|""[\w\s]*"""); 

O si lo necesita excluir "personajes:

Regex 
     .Matches(input, @"(?<match>\w+)|\""(?<match>[\w\s]*)""") 
     .Cast<Match>() 
     .Select(m => m.Groups["match"].Value) 
     .ToList() 
     .ForEach(s => Console.WriteLine(s)); 
+0

MUY CERCA! Ahora todo lo que necesito es preservar el espacio en blanco en los partidos. –

+3

+1 para usar el grupo con nombre para excluir las comillas _transparently_. –

+7

Si alguien está interesado, esta es una versión modificada de la expresión regular de Bartek que funciona para caracteres que no son palabras (por ejemplo, puntos, comas y corchetes): [^ \ s "] + |" [^ "] *" –

1

EDIT: Perdón por mi publicación anterior, obviamente esto es posible.

para manejar todos los caracteres no alfanuméricos se necesita algo como esto:

MatchCollection matchCollection = Regex.Matches(input, @"(?<match>[^""\s]+)|\""(?<match>[^""]*)"""); 
foreach (Match match in matchCollection) 
     { 
      yield return match.Groups["match"].Value; 
     } 

puede hacer que el foreach más inteligente si está utilizando .Net> 2,0

1

Shaun,

I cree que la siguiente expresión regular debería hacerlo

(?<=")\w[\w\s]*(?=")|\w+ 

Saludos,
Lieven

+0

2. Gracias por la respuesta, pero esto no parece tomar las cotizaciones en cuenta. –

+0

lo hace aquí? ¿Qué da? –

+0

Lo sentimos, tienes razón. Mi error –

4

Esta expresión regular se dividirá en función del caso anterior, aunque no elimina las comillas ni los espacios adicionales, por lo que es posible que desee realizar algún procesamiento posterior en sus cadenas. Sin embargo, esto debería mantener correctamente las cadenas entrecomilladas juntas.

"[^"]+"|\s?\w+?\s 
+0

Gracias por la respuesta. Esto está muy cerca. Lo suficientemente cerca que lo usaré por ahora. Dejaré la pregunta abierta durante aproximadamente un día para ver si hay una respuesta más completa. De lo contrario, aceptaré esto. –

+0

"([^"] +) "| \ s? (\ W +?) \ S devolverá" -stripped strings – f3lix

2

Con un poco de desorden, lenguajes regulares puede realizar un seguimiento de par/impar de conteo de las cotizaciones, pero si sus datos pueden incluir cotizaciones escapados (\ "), entonces estás en problemas reales producir o comprender una expresión regular que manejará eso correctamente.

0

Tome un vistazo a LSteinle de "Split Function that Supports Text Qualifiers" sobre al proyecto

Aquí Código es el fragmento de su proyecto que le interesa.

using System.Text.RegularExpressions; 

public string[] Split(string expression, string delimiter, string qualifier, bool ignoreCase) 
{ 
    string _Statement = String.Format("{0}(?=(?:[^{1}]*{1}[^{1}]*{1})*(?![^{1}]*{1}))", 
         Regex.Escape(delimiter), Regex.Escape(qualifier)); 

    RegexOptions _Options = RegexOptions.Compiled | RegexOptions.Multiline; 
    if (ignoreCase) _Options = _Options | RegexOptions.IgnoreCase; 

    Regex _Expression = New Regex(_Statement, _Options); 
    return _Expression.Split(expression); 
} 

Solo observar a llamar a esto en un bucle como su creación y compilando la declaración Regex cada vez que la llamas. Entonces, si necesitas llamarlo más seguido un puñado de veces, consideraría crear un caché Regex de algún tipo.

16

La solución de Lieven se lleva la mayor parte del camino, y como dice en sus comentarios, solo se trata de cambiar el final a la solución de Bartek. El resultado final es la siguiente expresiones regulares de trabajo:

(?<=")\w[\w\s]*(?=")|\w+|"[\w\s]*" 

de entrada: Aquí es "mi cadena" que tiene "seis partidos"

Salida:

  1. Aquí
  2. es
  3. "mi cadena"
  4. es
  5. tiene
  6. "seis partidos"

Por desgracia, es incluyendo las comillas. Si en lugar de utilizar el siguiente:

(("((?<token>.*?)(?<!\\)")|(?<token>[\w]+))(\s)*) 

y explícitamente capturar el "token" partidos de la siguiente manera: salida

RegexOptions options = RegexOptions.None; 
    Regex regex = new Regex(@"((""((?<token>.*?)(?<!\\)"")|(?<token>[\w]+))(\s)*)", options); 
    string input = @" Here is ""my string"" it has "" six matches"" "; 
    var result = (from Match m in regex.Matches(input) 
        where m.Groups[ "token" ].Success 
        select m.Groups[ "token" ].Value).ToList(); 

    for (int i = 0; i < result.Count(); i++) 
    { 
     Debug.WriteLine(string.Format("Token[{0}]: '{1}'", i, result[ i ])); 
    } 

Depuración:

Token[0]: 'Here' 
Token[1]: 'is' 
Token[2]: 'my string' 
Token[3]: 'it' 
Token[4]: 'has' 
Token[5]: ' six matches' 
+0

necesito una expresión regular para la función javascript split() para dividir palabras en espacios en blanco, excepto las de citas. No pude usar la que escribiste, ¿sabes cómo escribir una en javascript? – ajsie

+0

Para cambiar esto, para que cuente otros símbolos como palabras, simplemente cambie el [\ w] para que coincida. Se estaba dividiendo en puntos decimales, así que lo cambié a [\ w.] Y ahora se divide correctamente. –

+0

Entonces, ¿cómo se ve la expresión regular cuando no se divide con Colons o:? –

0

Si desea tomar una Mire una solución general a este problema en la forma de un objeto javascript libre y de código abierto, puede visitar http://splitterjsobj.sourceforge.net/ para una demostración en vivo (y descargar). El objeto tiene las siguientes características:

  • Se pueden utilizar pares de caracteres de comillas definidos por el usuario para escapar del delimitador (evitar una división entre comillas). Las comillas se pueden escapar con un carácter de escape definido por el usuario y/o mediante "escape de doble cita". El escape char se puede escapar (consigo mismo). En una de las 5 matrices de salida (propiedades del objeto), la salida no está protegida. (Por ejemplo, si escape char = /, "a ///" b "no está protegido como a /" b)
  • Dividir en una matriz de delimitadores; analizar un archivo en una llamada.(Las matrices de salida estarán anidadas).
  • Todas las secuencias de escape reconocidas por javascript se pueden evaluar durante el proceso de división y/o en un preproceso.
  • funcionalidad de devolución de llamada
  • coherencia entre navegadores

El objeto también está disponible como un plugin de jQuery, sino como un nuevo usuario en este sitio que sólo pueden incluir un enlace en este mensaje.

+0

Espera, ¿qué? El OP está preguntando por .NET regexp. ¿Es esto un comercial para su lib, o hubo alguna manera en la que pensó que se integraría en .NET fácilmente? – ruffin

7

Estaba usando la respuesta de Bartek Szabat, pero necesitaba capturar más que solo caracteres "\ w" en mis tokens. Para resolver el problema, he modificado su expresión regular ligeramente, similar a la respuesta de Grzenio:

Regular Expression: (?<match>[^\s"]+)|(?<match>"[^"]*") 

C# String:   (?<match>[^\\s\"]+)|(?<match>\"[^\"]*\") 

código de Bartek (que devuelve fichas despojados de cotizaciones que encierran) se convierte en:

Regex 
     .Matches(input, "(?<match>[^\\s\"]+)|(?<match>\"[^\"]*\")") 
     .Cast<Match>() 
     .Select(m => m.Groups["match"].Value) 
     .ToList() 
     .ForEach(s => Console.WriteLine(s)); 
+1

publicado aquí con la esperanza de que alguien lo encuentre útil en un futuro lejano :) – Boinst

+1

Y si no quiere las comillas: 'Regex.Matches (línea," (? [^ \\ s \ "] +) | \ "(? [^ \"] *) \ "") ' –

7

La respuesta superior no bastante trabaja para mi. Estaba tratando de dividir este tipo de cadena por espacios, pero parece que se divide en los puntos ('.') También.

"the lib.lib" "another lib".lib 

sé la pregunta se refiere a regexs, pero terminé escribiendo una función no de expresiones regulares para hacer esto:

/// <summary> 
    /// Splits the string passed in by the delimiters passed in. 
    /// Quoted sections are not split, and all tokens have whitespace 
    /// trimmed from the start and end. 
    public static List<string> split(string stringToSplit, params char[] delimiters) 
    { 
     List<string> results = new List<string>(); 

     bool inQuote = false; 
     StringBuilder currentToken = new StringBuilder(); 
     for (int index = 0; index < stringToSplit.Length; ++index) 
     { 
      char currentCharacter = stringToSplit[index]; 
      if (currentCharacter == '"') 
      { 
       // When we see a ", we need to decide whether we are 
       // at the start or send of a quoted section... 
       inQuote = !inQuote; 
      } 
      else if (delimiters.Contains(currentCharacter) && inQuote == false) 
      { 
       // We've come to the end of a token, so we find the token, 
       // trim it and add it to the collection of results... 
       string result = currentToken.ToString().Trim(); 
       if (result != "") results.Add(result); 

       // We start a new token... 
       currentToken = new StringBuilder(); 
      } 
      else 
      { 
       // We've got a 'normal' character, so we add it to 
       // the curent token... 
       currentToken.Append(currentCharacter); 
      } 
     } 

     // We've come to the end of the string, so we add the last token... 
     string lastResult = currentToken.ToString().Trim(); 
     if (lastResult != "") results.Add(lastResult); 

     return results; 
    } 
+2

Espero que esta respuesta no se considere fuera de tema ya que es una función no regex. Encontré esta pregunta mientras buscaba el tema más general de cómo dividir una cadena mientras se conservan las comillas, en lugar de la pregunta más específica sobre las expresiones regulares. –

+0

esto es mucho más claro que encontrar una solución de expresión regular con sabor a C#. – timc

5

he encontrado la expresión regular en este answer a ser bastante útil. Para que funcione en C# tendrá que usar la clase MatchCollection.

//need to escape \s 
string pattern = "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"; 

MatchCollection parsedStrings = Regex.Matches(line, pattern); 

for (int i = 0; i < parsedStrings.Count; i++) 
{ 
    //print parsed strings 
    Console.Write(parsedStrings[i].Value + " "); 
} 
Console.WriteLine(); 
Cuestiones relacionadas