187 votes

Javascript et regex : diviser une chaîne et garder le séparateur

J'ai une corde :

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

Et je voudrais diviser cette chaîne avec le délimiteur <br /> suivi d'un caractère spécial.

Pour ce faire, j'utilise ceci :

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

J'obtiens ce dont j'ai besoin, sauf que je perds le délimiteur. Voici l'exemple : http://jsfiddle.net/JwrZ6/1/

Comment puis-je conserver le délimiteur ?

3voto

snnsnn Points 81

Si vous regroupez le motif de fractionnement, sa correspondance sera conservée dans la sortie et c'est à dessein :

Si separator est une expression régulière avec des parenthèses de capture, alors chaque fois que séparateur correspond, les résultats (y compris tout résultat non défini) non définis) des parenthèses de capture sont ajoutés au tableau de sortie. tableau.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#description

Vous n'avez pas besoin d'un drapeau lookahead ou global, sauf si votre modèle de recherche en utilise un.

const str = `How much wood would a woodchuck chuck, if a woodchuck could chuck wood?`

const result = str.split(/(\s+)/);
console.log(result);

// We can verify the result
const isSame = result.join('') === str;
console.log({ isSame });

Vous pouvez utiliser plusieurs groupes. Vous pouvez être aussi créatif que vous le souhaitez et ce qui reste en dehors des groupes sera supprimé :

const str = `How much wood would a woodchuck chuck, if a woodchuck could chuck wood?`

const result = str.split(/(\s+)(\w{1,2})\w+/);
console.log(result, result.join(''));

1voto

Berezh Points 181

Une fonction d'extension divise une chaîne de caractères avec une sous-chaîne ou un RegEx et le délimiteur est placé en fonction du deuxième paramètre devant ou derrière.

    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;
    };

Le test :

    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"]);
    });

1voto

J'ai utilisé ça :

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
  }, [])
}

Sauf que tu ne devrais pas t'embêter avec String.prototype alors voici une version fonctionnelle :

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
  }, [])
}

Donc vous pourriez le faire :

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

Et vous vous retrouverez avec :

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

1voto

joriki Points 508

La plupart des réponses existantes datent d'avant l'introduction du assertions "lookbehind en JavaScript en 2018. Vous n'avez pas précisé comment vous vouliez que les délimiteurs soient inclus dans le résultat. Un cas d'utilisation typique serait les phrases délimitées par la ponctuation ([. ?!]), où l'on voudrait que les délimiteurs soient inclus à la fin des chaînes de caractères résultantes. Cela correspond au quatrième cas de la réponse acceptée, mais comme indiqué dans cette réponse, cette solution ne fonctionne que pour les caractères uniques. Les chaînes arbitraires avec les délimiteurs ajoutés à la fin peuvent être formées avec une assertion lookbehind :

'It is. Is it? It is!'.split(/(?<=[.?!])/)
/* [ 'It is.', ' Is it?', ' It is!' ] */

-2voto

DoneDeal0 Points 1558

J'ai également trouvé cette solution. Pas besoin de regex, très lisible.

const str = "hello world what a great day today balbla"
const separatorIndex = str.indexOf("great")
const parsedString = str.slice(separatorIndex)

console.log(parsedString)

ou en une seule ligne :

const str = "hello what a great day today balbla"
const parsedString = str.indexOf(str.indexOf("great"))
console.log(parsedString)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X