2012-08-17 13 views
63

tengo una cadena:Javascript y el uso de expresiones regulares: Separar una cadena y mantener el separador de

var string = "aaaaaa<br />&dagger; bbbb<br />&Dagger; cccc" 

Y me gustaría dividir esta cadena con delimitador <br /> seguido por un carácter especial.

Para hacer eso, estoy usando esto:

string.split(/<br \/>&#?[a-zA-Z0-9]+;/g); 

estoy recibiendo lo que necesito, excepto que estoy perdiendo el delimitador. Aquí está el ejemplo: http://jsfiddle.net/JwrZ6/1/

¿Cómo puedo conservar el delimitador?

+0

si se conoce el delimitador de antemano, ¿por qué no hacer ... 'delim var = "
"; '? –

+0

Gracias @SiGanteng, conozco el delimitador anterior pero no puedo hacerlo funcionar para mi ejemplo. Necesito mantener el delimitador como
seguido del carácter especial porque a veces puedo tener un
no seguido por el carácter especial y este no tiene que ser dividido. –

+1

Buena pregunta, tengo un caso similar donde saber que el delimitador no ayuda. Me estoy dividiendo en "] y [". Entonces realmente mi delimitador es "&" pero dividirlo no es lo suficientemente preciso, necesito obtener los corchetes a cada lado para determinar una división adecuada. Sin embargo, necesito esos corchetes en mis cuerdas divididas. 1 en cada lado. – PandaWood

Respuesta

55

Uso positive lookahead de manera que la expresión regular afirma que existe el carácter especial, pero en realidad no coincide con él:

string.split(/<br \/>(?=&#?[a-zA-Z0-9]+;)/g); 

See it in action.

Actualización: error tipográfico fijo (literal movido dentro ; parens de búsqueda hacia delante)

+0

Muchas gracias Jon, esto resolvió mi problema. –

29

Si envuelve el delimitador en parantheses que será parte de la matriz devuelta.

string.split(/(<br \/>&#?[a-zA-Z0-9]+);/g); 
// returns ["aaaaaa", "<br />&dagger;", "bbbb", "<br />&Dagger;", "cccc"] 

Dependiendo de la parte que desea mantener el cambio qué subgrupo que coinciden

string.split(/(<br \/>)&#?[a-zA-Z0-9]+;/g); 
// returns ["aaaaaa", "<br />", "bbbb", "<br />", "cccc"] 

podría mejorar la expresión al ignorar el caso de las letras string.split (/() & #? [ a-z0-9] +;/gi);

Y puede hacer coincidir los grupos predefinidos como esto: \d es igual a [0-9]\w y es igual a [a-zA-Z0-9_]. Esto significa que tu expresión podría verse así.

string.split(/<br \/>(&#?[a-z\d]+;)/gi); 

Hay una buena Regular Expression Reference on JavaScriptKit.

+2

Mejor aún, no sé si podemos conservar solo una parte del delimitador. De hecho, necesito guardar solo el carácter especial, puedo hacerlo con esto: string.split (/
(& #? [A-zA-Z0-9] +;)/g); –

+1

Puede optimizar su expresión ignorando el caso de las palabras. O coincida con una clase de caracteres predefinida. Actualizaré mi respuesta. –

+1

Exactamente lo que estaba buscando ... ¡gracias .. !! –

0

Una función de extensión divide la cadena con subcadena o RegEx y el delimitador se coloca según el segundo parámetro adelante o atrás.

String.prototype.splitKeep = function (splitter, ahead) { 
     var self = this; 
     var result = []; 
     if (splitter != '') { 
      var matches = []; 
      // Getting mached value and its index 
      var replaceName = splitter instanceof RegExp ? "replace" : "replaceAll"; 
      var r = self[replaceName](splitter, function (m, i, e) { 
       matches.push({ value: m, index: i }); 
       return getSubst(m); 
      }); 
      // Finds split substrings 
      var lastIndex = 0; 
      for (var i = 0; i < matches.length; i++) { 
       var m = matches[i]; 
       var nextIndex = ahead == true ? m.index : m.index + m.value.length; 
       if (nextIndex != lastIndex) { 
        var part = self.substring(lastIndex, nextIndex); 
        result.push(part); 
        lastIndex = nextIndex; 
       } 
      }; 
      if (lastIndex < self.length) { 
       var part = self.substring(lastIndex, self.length); 
       result.push(part); 
      }; 
      // Substitution of matched string 
      function getSubst(value) { 
       var substChar = value[0] == '0' ? '1' : '0'; 
       var subst = ''; 
       for (var i = 0; i < value.length; i++) { 
        subst += substChar; 
       } 
       return subst; 
      }; 
     } 
     else { 
      result.add(self); 
     }; 
     return result; 
    }; 

La prueba:

test('splitKeep', function() { 
     // String 
     deepEqual("1231451".splitKeep('1'), ["1", "231", "451"]); 
     deepEqual("123145".splitKeep('1', true), ["123", "145"]); 
     deepEqual("1231451".splitKeep('1', true), ["123", "145", "1"]); 
     deepEqual("hello man how are you!".splitKeep(' '), ["hello ", "man ", "how ", "are ", "you!"]); 
     deepEqual("hello man how are you!".splitKeep(' ', true), ["hello", " man", " how", " are", " you!"]); 
     // Regex 
     deepEqual("mhellommhellommmhello".splitKeep(/m+/g), ["m", "hellomm", "hellommm", "hello"]); 
     deepEqual("mhellommhellommmhello".splitKeep(/m+/g, true), ["mhello", "mmhello", "mmmhello"]); 
    }); 
85

que estaba teniendo un problema similar pero ligeramente diferente. De todos modos, aquí hay ejemplos de tres escenarios diferentes para dónde guardar el delimitador.

"1、2、3".split("、") == ["1", "2", "3"] 
"1、2、3".split(/(、)/g) == ["1", "、", "2", "、", "3"] 
"1、2、3".split(/(?=、)/g) == ["1", "、2", "、3"] 
"1、2、3".split(/(?!、)/g) == ["1、", "2、", "3"] 
"1、2、3".split(/(.*?、)/g) == ["", "1、", "", "2、", "3"] 

Advertencia: El cuarto sólo funcionará para dividir caracteres individuales.ConnorsFan presenta an alternative:

// Split a path, but keep the slashes that follow directories 
var str = 'Animation/rawr/javascript.js'; 
var tokens = str.match(/[^\/]+\/?|\//g); 
+1

cosas muy buenas m8, gracias! –

+1

¡Excelente respuesta! –

+1

Salvaste mi día :) – noviewpoint

0

He estado usando este:

String.prototype.splitBy = function (delimiter) { 
    var 
    delimiterPATTERN = '(' + delimiter + ')', 
    delimiterRE = new RegExp(delimiterPATTERN, 'g'); 

    return this.split(delimiterRE).reduce((chunks, item) => { 
    if (item.match(delimiterRE)){ 
     chunks.push(item) 
    } else { 
     chunks[chunks.length - 1] += item 
    }; 
    return chunks 
    }, []) 
} 

Excepto que no debe meterse con String.prototype, así que aquí está una versión de función:

var splitBy = function (text, delimiter) { 
    var 
    delimiterPATTERN = '(' + delimiter + ')', 
    delimiterRE = new RegExp(delimiterPATTERN, 'g'); 

    return text.split(delimiterRE).reduce(function(chunks, item){ 
    if (item.match(delimiterRE)){ 
     chunks.push(item) 
    } else { 
     chunks[chunks.length - 1] += item 
    }; 
    return chunks 
    }, []) 
} 

Por lo que podría hacer:

var haystack = "aaaaaa<br />&dagger; bbbb<br />&Dagger; cccc" 
var needle = '<br \/>&#?[a-zA-Z0-9]+;'; 
var result = splitBy(string, haystack) 
console.log(JSON.stringify(result, null, 2)) 

Y usted va a terminar con:

[ 
    "<br />&dagger; bbbb", 
    "<br />&Dagger; cccc" 
] 
3

contestadas aquí también JavaScript Split Regular Expression keep the delimiter

utilizar el patrón de búsqueda hacia delante en la expresión regular ejemplo

var string = '500x500-11*90~1+1'; 
string = string.replace(/(?=[$-/:-?{-~!"^_`\[\]])/gi, ","); 
string = string.split(","); 

esta voluntad (= patrón?) darte el siguiente resultado

[ '500x500', '-11', '*90', '~1', '+1' ] 

también se puede dividir directamente

string = string.split(/(?=[$-/:-?{-~!"^_`\[\]])/gi); 

dando el mismo resultado

[ '500x500', '-11', '*90', '~1', '+1' ] 
+0

¿Por qué no se divide inmediatamente, como en la respuesta aceptada de Jon? – Gordon

+0

@Gordon ... :) Podría hacer eso ... actualicé el código ... Saludos – Fry

0
function formatDate(dt, format) { 
    var monthNames = [ 
     "Enero", "Febrero", "Marzo", 
     "Abril", "Mayo", "Junio", "Julio", 
     "Agosto", "Setiembre", "Octubre", 
     "Noviembre", "Diciembre" 
    ]; 
    var Days = [ 
     "Domingo", "Lunes", "Martes", "Miercoles", 
     "Jueves", "Viernes", "Sabado" 
    ]; 

    function pad(n, width, z) { 
     z = z || '0'; 
     n = n + ''; 
     return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; 
    } 

    function replace(val, date) { 
     switch (val) { 
      case 'yyyy': 
       return date.getFullYear(); 
      case 'YYYY': 
       return date.getFullYear(); 
      case 'yy': 
       return (date.getFullYear() + "").substring(2); 
      case 'YY': 
       return (date.getFullYear() + "").substring(2); 
      case 'MMMM': 
       return monthNames[date.getMonth()]; 
      case 'MMM': 
       return monthNames[date.getMonth()].substring(0, 3); 
      case 'MM': 
       return pad(date.getMonth() + 1, 2); 
      case 'M': 
       return date.getMonth() + 1; 
      case 'dd': 
       return pad(date.getDate(), 2); 
      case 'd': 
       return date.getDate(); 
      case 'DD': 
       return Days[date.getDay()]; 
      case 'D': 
       return Days[date.getDay()].substring(0, 3); 
      case 'HH': 
       return pad(date.getHours(), 2); 
      case 'H': 
       return date.getHours(); 
      case 'mm': 
       return pad(date.getMinutes(), 2); 
      case 'm': 
       return date.getMinutes(); 
      case 'ss': 
       return pad(date.getSeconds(), 2); 
      case 's': 
       return date.getSeconds(); 
      default: 
       return val; 
     } 
    } 

    var ds = format.split(/(|,|:)/g); 
    var newFormat = ''; 
    for (var i = 0; i < ds.length; i++) { 
     newFormat += replace(ds[i], dt); 
    } 
    return newFormat; 
} 

var a = "2016-08-22T16:02:05.645Z"; 
var d = new Date(Date.parse(a)); 
// var d = new Date(); 
console.log(formatDate(d, 'd de MMMM, de YYYY H:mm')); 
Cuestiones relacionadas