Javascript ve regex: dizeyi ayırın ve ayırıcıyı koruyun


133

Bir dizem var:

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

Ve bu dizgiyi ayırıcı ve <br />ardından özel bir karakterle bölmek istiyorum .

Bunu yapmak için şunu kullanıyorum:

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

Sınırlayıcıyı kaybetmem dışında ihtiyacım olanı alıyorum. İşte örnek: http://jsfiddle.net/JwrZ6/1/

Sınırlayıcıyı nasıl tutabilirim?


Sınırlayıcıyı önceden biliyorsanız, neden sadece ... var delim = "<br/>";?
Andreas Wong

Teşekkür ederim @SiGanteng, önceden ayırıcıyı biliyorum ama örneğim için çalışmasını sağlayamıyorum. Sınırlayıcıyı <br /> özel karakterin takip etmesi için tutmam gerekiyor çünkü bazen bir <br /> özel karakterin gelmemesi olabilir ve bu karakterin bölünmesi gerekmez.
Miloš

2
Güzel soru, sınırlayıcıyı bilmenin yardımcı olmadığı benzer bir durumum var. "] Ve [" bölümlerine ayrılıyorum. Yani gerçekte benim sınırlayıcım "&" ama buna ayırmak yeterince kesin değil, uygun bir ayırma belirlemek için her iki taraftaki parantezleri almam gerekiyor. Ancak, bu parantezlere bölünmüş dizelerime geri dönmem gerekiyor. Her iki tarafta da 1 tane.
PandaWood

Yanıtlar:


105

Normal ifadenin özel karakterin var olduğunu ancak gerçekte onunla eşleşmediğini iddia etmesi için (pozitif) ileriye bakma kullanın :

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

Eylemde görün:

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


Bu kodu kullandığımda 0, her dizenin sonuna bir ekliyor
keyboard-warrior

2
Verdiğiniz bağlantıda olumlu bakışla ilgili hiçbir şey bulamıyorum.
Paul Chris Jones

@PaulJones içerik, aradan geçen sürede taşındı. Bana haber verdiğiniz için teşekkürler, bağlantıyı düzelttim.
Jon

180

Benzer ama biraz farklı bir sorun yaşıyordum. Her neyse, burada sınırlayıcının nerede tutulacağına ilişkin üç farklı senaryo örnekleri verilmiştir.

"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"]

Uyarı: Dördüncü, yalnızca tek karakterleri bölmek için çalışacaktır. ConnorsFan bir alternatif sunar :

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

3
Üçüncü örnek gibi bir şey arıyordum, ancak bu yalnızca öğeler tek bir karakter olduğunda işe yarar - aksi takdirde tek tek karakterlere bölünür. Sonunda sıkıcı RegExp.exec yoluna gitmek zorunda kaldım .
Gordon

2
Herkesin neden / g kullandığını anlamıyorum
Sarsaparilla

1
Tam kelimeler için bu normal ifade "1、2、3" .split (/ (?! 、) / G) == ["1 、", "2 、", "3"] nasıl kullanılır? Örneğin "foo1, foo2, foo3,"
Waltari

Sen bir dahisin!. nasıl çalıştığını açıklayan belgeleri nerede buluyorsunuz? gbir sona ihtiyacın yok
pery mimon

1
.matchBu örnekler için açgözlü olmayan çözümün çevirisi : "11、22、33".match(/.*?、|.+$/g)-> ["11、", "22、", "33"]. Not /gdeğiştirici, eşleşme için çok önemlidir.
Beni Cherniavsky-Paskin

57

Sınırlayıcıyı parantez içine alırsanız, döndürülen dizinin parçası olur.

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

Hangi bölüme uymak istediğinize bağlı olarak hangi alt grubu eşleştirdiğinizi değiştirin

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

İfadeyi, harflerin büyük / küçük harf durumunu görmezden gelerek geliştirebilirsiniz string.split (/ () & #? [A-z0-9] +; / gi);

Ve bunun gibi önceden tanımlanmış grupları eşleştirebilirsiniz: \deşittir [0-9]ve \weşittir [a-zA-Z0-9_]. Bu, ifadenizin böyle görünebileceği anlamına gelir.

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

JavaScriptKit'te iyi bir Normal İfade Referansı vardır .


4
Daha da iyisi, sınırlayıcının sadece bir kısmını tutabileceğimizi bilmiyorum. Aslında sadece özel karakteri tutmam gerekiyor, bunu şu şekilde yapabilirim: string.split (/ <br \/> (& #? [A-zA-Z0-9] +;) / g);
Miloš

1
Kelimelerin durumunu görmezden gelerek ifadenizi optimize edebilirsiniz. Veya önceden tanımlanmış bir karakter sınıfıyla eşleştirin. Cevabımı güncelleyeceğim.
Torsten Walter

2
Neden bu kadar düşük .. Mükemmel ve çok esnek
Tofandel

2
Bu kesinlikle en kolay yol ve en okunabilir sözdizimidir.
Timar Ivo Batis

4

burada da cevapladı JavaScript Bölünmüş Normal İfade sınırlayıcıyı koruyun

normal ifade örneğindeki (? = desen) ilerleme modelini kullanın

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

bu size aşağıdaki sonucu verecektir.

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

Doğrudan bölünebilir

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

aynı sonucu vermek

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

Jon'un kabul ettiği cevapta olduğu gibi neden hemen ayrılmıyorsunuz?
Gordon

@Gordon ... :) Bunu yapabilirdim ... kodu güncelledim ... Şerefe
Fry

2

Jichi'nin cevabında bir değişiklik yaptım ve onu birden çok harfi de destekleyen bir fonksiyona koydum.

String.prototype.splitAndKeep = function(separator, method='seperate'){
    var str = this;
    if(method == 'seperate'){
        str = str.split(new RegExp(`(${separator})`, 'g'));
    }else if(method == 'infront'){
        str = str.split(new RegExp(`(?=${separator})`, 'g'));
    }else if(method == 'behind'){
        str = str.split(new RegExp(`(.*?${separator})`, 'g'));
        str = str.filter(function(el){return el !== "";});
    }
    return str;
};

jichi'nin cevapları 3. yöntem bu fonksiyonda çalışmayacağı için 4. yöntemi aldım ve aynı sonucu elde etmek için boş alanları kaldırdım.

edit: char1 veya char2'yi bölmek için bir diziyi hariç tutan ikinci yöntem

String.prototype.splitAndKeep = function(separator, method='seperate'){
    var str = this;
    function splitAndKeep(str, separator, method='seperate'){
        if(method == 'seperate'){
            str = str.split(new RegExp(`(${separator})`, 'g'));
        }else if(method == 'infront'){
            str = str.split(new RegExp(`(?=${separator})`, 'g'));
        }else if(method == 'behind'){
            str = str.split(new RegExp(`(.*?${separator})`, 'g'));
            str = str.filter(function(el){return el !== "";});
        }
        return str;
    }
    if(Array.isArray(separator)){
        var parts = splitAndKeep(str, separator[0], method);
        for(var i = 1; i < separator.length; i++){
            var partsTemp = parts;
            parts = [];
            for(var p = 0; p < partsTemp.length; p++){
                parts = parts.concat(splitAndKeep(partsTemp[p], separator[i], method));
            }
        }
        return parts;
    }else{
        return splitAndKeep(str, separator, method);
    }
};

kullanımı:

str = "first1-second2-third3-last";

str.splitAndKeep(["1", "2", "3"]) == ["first", "1", "-second", "2", "-third", "3", "-last"];

str.splitAndKeep("-") == ["first1", "-", "second2", "-", "third3", "-", "last"];

1

Bir uzantı işlevi dizeyi alt dize veya RegEx ile böler ve sınırlayıcı ikinci parametreye göre öne veya arkaya yerleştirilir.

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

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

0

Bunu kullanıyorum:

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

Uğraşmamalısınız dışında String.prototype, işte bir işlev sürümü:

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

Böylece yapabilirsin:

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) )

Ve şununla sonuçlanacaksın:

[
  "<br />&dagger; bbbb",
  "<br />&Dagger; cccc"
]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.