Divida las oraciones por ',' y elimine los espacios circundantes

82

Tengo este codigo:

var r = /(?:^\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*){0,}$/
var s = "   a   ,  b  , c "
var m = s.match(r)
m => ["   a   ,  b  , c ", "a", "c"]

Parece que toda la cadena ha coincidido, pero ¿a dónde se ha "b"ido? Preferiría esperar obtener:

["   a   ,  b  , c ", "a", "b", "c"]

para que pueda hacer m.shift()con un resultado como s.split(',')pero también con los espacios en blanco eliminados.

¿Tengo un error en la expresión regular o no lo entiendo String.prototype.match?

meandre
fuente
Como nota al margen, {0,}es lo mismo que *.
pimvdb
bueno, stambién puede ser ' a, c'o'a,b,c d e, f'
meandre
Cambiaré los

Respuestas:

190

Aquí hay una forma bastante simple y directa de hacer esto sin necesidad de una expresión regular compleja.

var str = "   a   ,  b  , c "
var arr = str.split(",").map(function(item) {
  return item.trim();
});
//arr = ["a", "b", "c"]

El nativo .mapes compatible con IE9 y versiones posteriores: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map


O en ES6 + se vuelve aún más corto:

var arr = str.split(",").map(item => item.trim());

Y para completar, aquí está en TypeScript con información de escritura.

var arr: string[] = str.split(",").map((item: string) => item.trim());
CBarr
fuente
4
Para ser quisquilloso, puede eliminar las llaves alrededor del argumento del mapa: var arr = str.split(",").map(item=>item.trim());
David Jones
Estoy con @DavidJones en este. Si modificas tu respuesta sería genial. Me ayudó mucho en mi caso, ¡gracias chicos!
Ya tomado en realidad
Sí, buen punto: ¡respuesta actualizada para reflejar eso! Personalmente, siempre agrego los paréntesis, ya que normalmente escribo Typecript y me gusta proporcionar la información de tipo explícita para que siempre pueda saber qué es algo de un vistazo.
CBarr
Esta es una gran respuesta Chris.
cíclico
Sencillo y lo mejor !!
Rahul Sonwanshi
22

Puede probar esto sin expresiones regulares complejas.

var arr = "   a   ,  b  , c ".trim().split(/\s*,\s*/);
console.log(arr);

xfg
fuente
15

Respuesta corta: use m = s.match(/[^ ,]/g);


Su RE no funciona como se esperaba, porque el último grupo coincide con la coincidencia más reciente (= c). Si omite {1,}$, la coincidencia devuelta será " a , b ", "a", "b". En resumen, su RegExp devuelve tantas coincidencias como grupos especificados a menos que use una globalbandera /g. En este caso, la lista devuelta contiene referencias a todas las subcadenas coincidentes.

Para lograr su efecto, use:

m = s.replace(/\s*(,|^|$)\s*/g, "$1");

Este reemplazo reemplaza cada coma ( ,), comienzo ( ^) y final ( $), rodeado por espacios en blanco, por el carácter original ( comma, o nada).

Si desea obtener una matriz, use:

m = s.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/);

Este RE recorta la cadena (elimina todos los espacios en blanco al principio y al final, luego divide la cadena por <any whitespace>,<any whitespace>. Tenga en cuenta que los caracteres de espacio en blanco también incluyen nuevas líneas y tabulaciones. Si desea ceñirse solo a los espacios, use un espacio ( ) en lugar de \s.

Rob W
fuente
@Andrew He ampliado la explicación de tu RE. Vea mi segundo ejemplo para un splitmétodo.
Rob W
Ya lo he publicado como comentario a otra respuesta. Me pregunto, ¿puedo hacerlo con una expresión regular y una operación o js regexp no es lo suficientemente inteligente?
meandre
@Andrew Sí, solo usa s.match(/[^ ,]+/g). Como se mencionó en la parte superior de mi respuesta, /ges la bandera global, que devuelve todas las subcadenas coincidentes.
Rob W
@Andrew: Un grupo de captura crea una coincidencia, sin importar cuántos cuantificadores agregue. Si desea hacer coincidir a, by c, se necesitan tres pares de paréntesis (sin incluir (?:...)):/(?:^\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)$/
user123444555621
@RobW, s.match (/ [^,] + / g) funciona exactamente como lo necesito, agréguelo a su respuesta
meandre
13

ES6 taquigrafía:

str.split(',').map(item=>item.trim())
Dieter Gribnitz
fuente
8

Puede hacer esto para su propósito
EDITAR : Eliminar el segundo reemplazo como se sugiere en los comentarios. s.replace(/^\s*|\s*$/g,'').split(/\s*,\s*/)
Primero replacerecorta la cadena y luego la splitfunción se divide '\s*,\s*'. Esto da salida ["a", "b", "c"]a la entrada " a , b , c "

En cuanto a por qué su expresión regular no captura 'b', está repitiendo un grupo capturado, por lo que solo se captura la última aparición. Más sobre eso aquí http://www.regular-expressions.info/captureall.html

Narendra Yadala
fuente
No quiero borrar todos los espacios en blanco, solo alrededor de comas o al principio / final de una cadena
meandre
@Andrew, ¿no son todos los espacios en blanco? ¿O tienes oraciones que deseas dividir?
David Hellsing
s.replace (/ ^ \ s * /, '') .replace (/ \ s * $ /, '') .split (/ \ s *, \ s * /) puede hacer esto
meandre
@Andrew Cambió la respuesta según sus requisitos.
Narendra Yadala
6

así que finalmente fui con /(?=\S)[^,]+?(?=\s*(,|$))/g, que proporciona exactamente lo que necesito: todas las oraciones divididas por ',' sin espacios circundantes.

'       a,    OMG     abc b a b, d o WTF        foo     '.
  match( /(?=\S)[^,]+?(?=\s*(,|$))/g )
=> ["a", "OMG     abc b a b", "d o WTF        foo"]

¡muchas gracias!

meandre
fuente
aquí está el significado tal como yo lo entiendo. corríjame si no estoy en lo cierto: (?=\S)- comience a capturar solo cuando no haya espacios en blanco al frente [^,]+- capture la mayor cantidad posible de "no comas" ?- pero no capture lo que pueda ser capturado por el siguiente grupo (?=\s*(,|$))- capture todos los espacios en blanco antes una coma o el final de la cadena /g- repita en toda la cadena
meandre
1

Si desea seguir usando expresiones regulares, mantenga el código simple y sin usar ES6:

s.replace(/ /g, '').split(",")

1 - Reemplaza todos los espacios (/ / g) por cadenas vacías ('')

2 - Luego divídelo en una matriz

Et voila

AlbertSY
fuente
Ésta es la mejor respuesta y la menos complicada.
Blazes