2011-11-17 23 views
11

Actualmente estoy luchando para encontrar una expresión regular que pueda dividir una cadena en palabras donde las palabras se definen como una secuencia de caracteres rodeada de espacios en blanco, o entre comillas dobles. Estoy usando String#scanRuby Regex extrayendo palabras

Por ejemplo, la cadena:

' hello "my name" is "Tom"' 

debe coincidir con las palabras:

hello 
my name 
is 
Tom 

me las arreglé para que coincida con las palabras entre comillas dobles usando:

/"([^\"]*)"/ 

pero no entiendo cómo incorporar los caracteres encerrados en espacios en blanco a obtener 'hola', 'es' y 'Tom' mientras que al mismo tiempo no arruine 'mi nombre'.

¡Cualquier ayuda con esto sería apreciada!

Respuesta

23
result = ' hello "my name" is "Tom"'.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/) 

funcionará para usted. Se imprimirá

=> ["", "hello", "\"my name\"", "is", "\"Tom\""] 

Simplemente ignore las cadenas vacías.

Explicación

" 
\\s   # Match a single character that is a “whitespace character” (spaces, tabs, and line breaks) 
    +    # Between one and unlimited times, as many times as possible, giving back as needed (greedy) 
(?=   # Assert that the regex below can be matched, starting at this position (positive lookahead) 
    (?:   # Match the regular expression below 
     [^\"]   # Match any character that is NOT a “\"” 
     *    # Between zero and unlimited times, as many times as possible, giving back as needed (greedy) 
     \"    # Match the character “\"” literally 
     [^\"]   # Match any character that is NOT a “\"” 
     *    # Between zero and unlimited times, as many times as possible, giving back as needed (greedy) 
     \"    # Match the character “\"” literally 
    )*   # Between zero and unlimited times, as many times as possible, giving back as needed (greedy) 
    [^\"]   # Match any character that is NOT a “\"” 
     *    # Between zero and unlimited times, as many times as possible, giving back as needed (greedy) 
    \$    # Assert position at the end of a line (at the end of the string or before a line break character) 
) 
" 

Puede utilizar reject como esto para evitar las cadenas vacías

result = ' hello "my name" is "Tom"' 
      .split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/).reject {|s| s.empty?} 

grabados

=> ["hello", "\"my name\"", "is", "\"Tom\""] 
+0

+1. ¡Buena respuesta! – Swanand

+0

Gran disección de la expresión regular. Muy útil. –

+0

esto no elimina caracteres especiales .. –

4
text = ' hello "my name" is "Tom"' 

text.scan(/\s*("([^"]+)"|\w+)\s*/).each {|match| puts match[1] || match[0]} 

Produce:

hello 
my name 
is 
Tom 

Explicación:

0 o más espacios seguidos por

ya sea

algunas palabras entre comillas dobles OR

una sola palabra

seguido por 0 o más espacios

+0

Lo que el OP está preguntando, no es posible sin mirar hacia adelante. – Swanand

+1

No estoy seguro de por qué pensaría que ... –

+0

Me refería a la solución original, donde solo se usa una expresión regular para dividir. Cualquier procesamiento posterior no era lo que tenía en mente. – Swanand

1

Puede probar esta expresión regular:

/\b(\w+)\b/ 

el cual utiliza \b para encontrar el límite de palabra. Y este sitio web http://rubular.com/ es útil.

+3

Esto no funciona. No intenta capturar entre las comillas como una sola coincidencia –

Cuestiones relacionadas