2015-06-03 10 views
12

Diciamo che ho una stringa: "We.need..to...split.asap". Quello che mi piacerebbe fare è dividere la stringa dal delimitatore ., ma desidero solo dividere il prima. e includere gli eventuali ricorrenti . s nel token successivo.Come dividere una stringa con un carattere non preceduto direttamente da un personaggio dello stesso tipo?

risultato atteso:

["We", "need", ".to", "..split", "asap"] 

In altre lingue, so che questo è possibile con un look-behind /(?<!\.)\./ ma Javascript purtroppo non supporta tale caratteristica.

Sono curioso di vedere le vostre risposte a questa domanda. Forse c'è un intelligente uso di look-ahead che attualmente mi sfugge?

Stavo considerando invertire la stringa, poi ri-invertire i segni, ma che sembra troppo lavoro per quello che sono dopo ... più polemiche: How do you reverse a string in place in JavaScript?

Grazie per l'aiuto!

+1

'" We.need..to ... split.asap ".split (/ \ b \ ./)', ma funziona solo se il primo '.' è preceduto da un carattere di parola. – nhahtdh

risposta

5

Ecco una variazione di the answer by guest271314 che gestisce più di due delimitatori consecutivi:

var text = "We.need.to...split.asap"; 
var re = /(\.*[^.]+)\./; 
var items = text.split(re).filter(function(val) { return val.length > 0; }); 

usa il dettaglio che se l'espressione di divisione comprende un gruppo di acquisizione, gli elementi catturati sono inclusi nell'array restituito. Questi gruppi di cattura sono in realtà l'unica cosa a cui siamo interessati; i token sono tutte stringhe vuote, che filtriamo.

EDIT: Sfortunatamente c'è forse un piccolo bug in questo. Se il testo da dividere inizia con un delimitatore, questo verrà incluso nel primo token. Se questo è un problema, si può rimediare con:

var re = /(?:^|(\.*[^.]+))\./; 
var items = text.split(re).filter(function(val) { return !!val; }); 

(credo che questo regex è brutto e auspica un miglioramento.)

2

Nota: Questa risposta non può gestire più di 2 delimitatori consecutivi, poiché è stato scritto secondo l'esempio in the revision 1 of the question, che non era molto chiaro su tali casi.


var text = "We.need.to..split.asap"; 
 
// split "." if followed by "." 
 
var res = text.split(/\.(?=\.)/).map(function(val, key) { 
 
    // if `val[0]` does not begin with "." split "." 
 
    // else split "." if not followed by "." 
 
    return val[0] !== "." ? val.split(/\./) : val.split(/\.(?!.*\.)/) 
 
}); 
 
// concat arrays `res[0]` , `res[1]` 
 
res = res[0].concat(res[1]); 
 

 
document.write(JSON.stringify(res));

+0

È intelligente, ma non può gestire più di 2 delimitatori consecutivi. ex: "we.need.to ... split.asap". La voterò, però, dato che non era chiaramente chiaro nell'esempio della domanda. – DRAB

+3

@DRAB Forse include _ "gestisce più di 2 delimitatori consecutivi. Es:" we.need.to ... split.asap "" _ "poiché ciò non era chiaramente chiaro nell'esempio della domanda." _ Alla domanda? – guest271314

+3

Più di due delimitatori erano implicati dall'uso del plurale da parte dell'OP: "qualsiasi". Ricorrente "ricorrente. –

3

È possibile farlo senza alcun lookaheads:

var subject = "We.need.to....split.asap"; 
 
var regex = /\.?(\.*[^.]+)/g; 
 

 
var matches, output = []; 
 

 
while(matches = regex.exec(subject)) { 
 
    output.push(matches[1]); 
 
} 
 

 
document.write(JSON.stringify(output));

sembrava che sarebbe lavorare in una sola riga, come ha fatto il https://regex101.com/r/cO1dP3/1, ma doveva essere ampliato nel codice sopra perché l'opzione /g impedisce per impostazione predefinita ai gruppi di acquisizione di ritornare con .match (ad es. i dati corretti erano nei gruppi di cattura, ma non potevamo accedervi immediatamente senza fare quanto sopra).

Vedi: JavaScript Regex Global Match Groups

Una soluzione alternativa con l'originale uno di linea (più una riga) è:

document.write(JSON.stringify(
 
    "We.need.to....split.asap".match(/\.?(\.*[^.]+)/g) 
 
     .map(function(s) { return s.replace(/^\./, ''); }) 
 
));

fare la vostra scelta!

+0

Questo isn ciò che OP vuole, che include ** tutti tranne uno ** delimitatore precedente in ciascun token. (In altre parole, il risultato dovrebbe essere '[" We "," need "," to "," ... split "," asap "]'. –

+0

Lo so, c'è stato un problema quando si sposta la regex da regex101 .com a qui. Dovrebbe funzionare ora, ma non più 1 riga :( –

+0

Molto meglio. +1 –

Problemi correlati