2008-09-15 16 views
6

Necesito apoyar frases exactas (entre comillas) en una lista de términos separados por el resto del espacio. Por lo tanto, dividir la cadena respectiva por el espacio-carácter ya no es suficiente.cadenas de análisis: extracción de palabras y frases [JavaScript]

Ejemplo:

input : 'foo bar "lorem ipsum" baz' 
output: ['foo', 'bar', 'lorem ipsum', 'baz'] 

Me pregunto si esto se podría lograr con un solo RegEx, en lugar de realizar las operaciones de análisis sintáctico o división y reincorporarse complejos.

¡Cualquier ayuda sería muy apreciada!

Respuesta

12
var str = 'foo bar "lorem ipsum" baz'; 
var results = str.match(/("[^"]+"|[^"\s]+)/g); 

... devuelve la matriz que está buscando.
Nótese, sin embargo:

  • cotizaciones de enmarcado se incluyen, por lo que se puede quitar con replace(/^"([^"]+)"$/,"$1") en los resultados.
  • Los espacios entre las comillas permanecerán intactos. Entonces, si hay tres espacios entre lorem y ipsum, estarán en el resultado. Puede solucionarlo ejecutando replace(/\s+/," ") en los resultados.
  • Si no hay cierre " después ipsum (es decir, una frase citada incorrectamente) que va a terminar con: ['foo', 'bar', 'lorem', 'ipsum', 'baz']
+1

El único problema con esto es que todas las cotizaciones son despojados - es decir, los caracteres de comillas en sí no son de búsqueda. –

0
'foo bar "lorem ipsum" baz'.match(/"[^"]*"|\w+/g); 

las cotizaciones delimitadores sean incluidos, aunque

0

Una expresión regular sencilla hará pero deje las comillas. p.ej.

'foo bar "lorem ipsum" baz'.match(/("[^"]*")|([^\s"]+)/g) 
output: ['foo', 'bar', '"lorem ipsum"', 'baz'] 

edición: golpeado a ella por Shyamsundar, lo siento por el doble respuesta

1

¿qué tal,

output = /(".+?"|\w+)/g.exec(input) 

luego hacer un pase sobre la producción de perder las cotizaciones.

alternativamente,

output = /"(.+?)"|(\w+)/g.exec(input) 

luego hacer una salida de paso n perder las capturas vacías.

2

Prueba esto:

var input = 'foo bar "lorem ipsum" baz'; 
var R = /(\w|\s)*\w(?=")|\w+/g; 
var output = input.match(R); 

output is ["foo", "bar", "lorem ipsum", "baz"] 

cuenta que no hay comillas dobles adicionales alrededor lorem ipsum

Aunque asume que la entrada tiene las comillas dobles en el lugar correcto:

var input2 = 'foo bar lorem ipsum" baz'; var output2 = input2.match(R); 
var input3 = 'foo bar "lorem ipsum baz'; var output3 = input3.match(R); 

output2 is ["foo bar lorem ipsum", "baz"] 
output3 is ["foo", "bar", "lorem", "ipsum", "baz"] 

Y no manejará escapado comillas dobles (es eso un problema?):

var input4 = 'foo b\"ar bar\" \"bar "lorem ipsum" baz'; 
var output4 = input4.match(R); 

output4 is ["foo b", "ar bar", "bar", "lorem ipsum", "baz"] 
0

Si se preguntaba cómo construir la expresión regular a sí mismo, es posible que desee comprobar hacia fuera Expresso (Expresso link) .Es una gran herramienta para aprender a construir expresiones regulares para que sepa lo que significa la sintaxis.

Cuando haya creado su propia expresión, puede realizar un .match en ella.

1

¡Muchas gracias por las respuestas rápidas!

He aquí un resumen de las opciones, para la posteridad:

var input = 'foo bar "lorem ipsum" baz'; 

output = input.match(/("[^"]+"|[^"\s]+)/g); 
output = input.match(/"[^"]*"|\w+/g); 
output = input.match(/("[^"]*")|([^\s"]+)/g) 
output = /(".+?"|\w+)/g.exec(input); 
output = /"(.+?)"|(\w+)/g.exec(input); 

Para el registro, aquí está la abominación que había llegado con:

var input = 'foo bar "lorem ipsum" "dolor sit amet" baz'; 
var terms = input.split(" "); 

var items = []; 
var buffer = []; 
for(var i = 0; i < terms.length; i++) { 
    if(terms[i].indexOf('"') != -1) { // outer phrase fragment -- N.B.: assumes quote is either first or last character 
     if(buffer.length === 0) { // beginning of phrase 
      //console.log("start:", terms[i]); 
      buffer.push(terms[i].substr(1)); 
     } else { // end of phrase 
      //console.log("end:", terms[i]); 
      buffer.push(terms[i].substr(0, terms[i].length - 1)); 
      items.push(buffer.join(" ")); 
      buffer = []; 
     } 
    } else if(buffer.length != 0) { // inner phrase fragment 
     //console.log("cont'd:", terms[i]); 
     buffer.push(terms[i]); 
    } else { // individual term 
     //console.log("standalone:", terms[i]); 
     items.push(terms[i]); 
    } 
    //console.log(items, "\n", buffer); 
} 
items = items.concat(buffer); 

//console.log(items); 
0

uno que sea fácil de entender y una solución general . Funciona para todos los delimitadores y caracteres 'join'. También es compatible con 'unido' palabras que son más de dos palabras de extensión .... es decir, listas como

"hello my name is 'jon delaware smith fred' I have a 'long name'" ....

Un poco como la respuesta de AC, pero un poco más ordenado ...

function split(input, delimiter, joiner){ 
    var output = []; 
    var joint = []; 
    input.split(delimiter).forEach(function(element){ 
     if (joint.length > 0 && element.indexOf(joiner) === element.length - 1) 
     { 
      output.push(joint.join(delimiter) + delimiter + element); 
      joint = []; 
     } 
     if (joint.length > 0 || element.indexOf(joiner) === 0) 
     { 
      joint.push(element); 
     } 
     if (joint.length === 0 && element.indexOf(joiner) !== element.length - 1) 
     { 
      output.push(element); 
      joint = []; 
     } 
    }); 
    return output; 
    } 
0

Esto podría ser una respuesta muy tarde, pero estoy interesado en responder

([\w]+|\"[\w\s]+\") 

http://regex101.com/r/dZ1vT6/72

ejemplo javascript puro

'The rain in "SPAIN stays" mainly in the plain'.match(/[\w]+|\"[\w\s]+\"/g) 

Salidas:

["The", "rain", "in", ""SPAIN stays"", "mainly", "in", "the", "plain"] 
0

ES6 solución de soporte:

  • dividida por el espacio a excepción de las cotizaciones en el interior
  • cotizaciones de Extracción pero no para la barra invertida escapó cotizaciones
  • Escaped q uote convertido en la cita

Código:

input.match(/\\?.|^$/g).reduce((p, c) => { 
     if(c === '"'){ 
      p.quote ^= 1; 
     }else if(!p.quote && c === ' '){ 
      p.a.push(''); 
     }else{ 
      p.a[p.a.length-1] += c.replace(/\\(.)/,"$1"); 
     } 
     return p; 
    }, {a: ['']}).a 

Salida:

[ 'foo', 'bar', 'lorem ipsum', 'baz' ] 
Cuestiones relacionadas