자바 스크립트 및 정규식 : 문자열을 분할하고 구분 기호 유지


132

문자열이 있습니다.

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

그리고이 문자열을 구분 기호 <br />뒤에 특수 문자 로 나누고 싶습니다 .

이를 위해 다음을 사용합니다.

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

구분 기호를 잃어버린 것을 제외하고는 필요한 것을 얻고 있습니다. 예 : http://jsfiddle.net/JwrZ6/1/

구분자를 어떻게 유지할 수 있습니까?


사전에 구분자를 알고 있다면 그냥하지 var delim = "<br/>";않겠습니까 ... ?
Andreas Wong

@SiGanteng 감사합니다. 사전 구분 기호를 알고 있지만 제 예에서는 작동하지 않습니다. 구분 기호 뒤에 특수 문자가 오는 <br />을 유지해야합니다. 때로 특수 문자가 뒤 따르지 않는 <br />을 가질 수 있고이 문자를 분할 할 필요가 없기 때문입니다.
Miloš

2
좋은 질문입니다. 구분 기호를 아는 것이 도움이되지 않는 비슷한 경우가 있습니다. "] & ["로 분할합니다. 그래서 실제로 내 구분 기호는 "&"이지만 분할하는 것은 충분히 정확하지 않습니다. 적절한 분할을 결정하려면 양쪽 대괄호를 가져와야합니다. 그러나 분할 문자열에 이러한 대괄호가 다시 필요합니다. 양쪽에 각각 1 개씩.
PandaWood

답변:


104

정규식이 특수 문자가 존재하지만 실제로 일치하지 않는다고 주장하도록 (양수) 미리보기를 사용 합니다.

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

실제 사용 방법 :

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


이 코드를 사용하는 경우, 그것은을 추가 0각 문자열의 끝에서
키보드 전사

2
귀하가 제공 한 링크에서 긍정적 인 예측에 대해 아무것도 찾을 수 없습니다.
Paul Chris Jones

@PaulJones 콘텐츠가 중간 시간에 이동되었습니다. 알려 주셔서 감사합니다. 링크를 수정했습니다.
Jon

180

나는 비슷하지만 약간 다른 문제가 있었다. 어쨌든, 다음은 구분자를 유지할 위치에 대한 세 가지 시나리오의 예입니다.

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

경고 : 네 번째는 단일 문자 분할에만 작동합니다. ConnorsFan 은 대안을 제시 합니다 .

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

3
세 번째 예제와 같은 것을 찾고 있었지만 요소가 하나의 문자 인 경우에만 작동합니다. 그렇지 않으면 개별 문자로 분할됩니다. 결국 지루한 RegExp.exec 경로를 따라야 했습니다.
Gordon

2
나는 모든 사람이 / g 사용하는 이유를 이해하지 않습니다
인삼차

1
전체 단어에 대해이 정규식 "1、2、3".split (/ (?! 、) / g) == [ "1 、", "2 、", "3"]을 어떻게 사용합니까? 예를 들어 "foo1은,에서는 foo2, foo3"
월 테리

당신은 천재입니다!. 작동 방식을 설명하는 문서를 어디서 찾을 수 있습니까? 당신은 필요하지 않습니다 ga를 끝
pery 미몬

1
.match다음 예제에 대한 탐욕스럽지 않은 솔루션 의 번역 : "11、22、33".match(/.*?、|.+$/g)-> ["11、", "22、", "33"]. 참고 /g수정자는 일치에 중요합니다.
Beni Cherniavsky-Paskin

57

구분 기호를 괄호로 묶으면 반환 된 배열의 일부가됩니다.

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

유지하려는 부분에 따라 일치하는 하위 그룹을 변경하십시오.

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

문자의 대소 문자를 무시하여 표현식을 향상시킬 수 있습니다. string.split (/ () & #? [a-z0-9] +; / gi);

그리고 다음과 같이 미리 정의 된 그룹에 대해 일치시킬 수 있습니다 : \d같음 [0-9]\w같음 [a-zA-Z0-9_]. 이것은 당신의 표정이 이렇게 보일 수 있음을 의미합니다.

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

JavaScriptKit에 좋은 정규 표현식 참조가 있습니다.


4
더 좋은 점은 구분 기호의 일부만 유지할 수 있다는 것입니다. 실제로 특수 문자 만 유지하면되며 다음과 같이 할 수 있습니다. string.split (/ <br \/> (& #? [a-zA-Z0-9] +;) / g);
Miloš

1
단어의 대소 문자를 무시하여 표현을 최적화 할 수 있습니다. 또는 미리 정의 된 문자 클래스와 일치합니다. 내 대답을 업데이트하겠습니다.
Torsten Walter

2
왜 그렇게 저 ... 그 완벽하고 매우 유연한입니다
Tofandel

2
이것은 확실히 가장 쉬운 방법이며 가장 읽기 쉬운 구문입니다.
Timar Ivo Batis

4

여기에 대답했습니다 .JavaScript Split Regular Expression은 구분 기호를 유지합니다.

정규식 예제에서 (? = pattern) lookahead 패턴 사용

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

이것은 당신에게 다음과 같은 결과를 줄 것입니다.

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

직접 분할 가능

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

같은 결과를주는

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

Jon의 대답 에서처럼 즉시 분리하지 않는 이유는 무엇입니까?
Gordon

@Gordon는 ... :) 난 그냥 그렇게 할 수 ... 업데이트 코드를 ... 건배
프라이

2

jichi의 ​​대답을 수정하여 여러 문자를 지원하는 기능에 넣었습니다.

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의 ​​답변 세 번째 방법은이 기능에서 작동하지 않으므로 네 번째 방법을 취하고 동일한 결과를 얻기 위해 빈 공간을 제거했습니다.

편집 : char1 또는 char2를 분할하는 배열을 제외한 두 번째 방법

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

용법:

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

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

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

1

확장 함수는 문자열을 부분 문자열 또는 RegEx로 분할하고 구분 기호는 두 번째 매개 변수의 앞 또는 뒤에 배치됩니다.

    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('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

나는 이것을 사용하고있다 :

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

를 엉망으로 만들면 안된다는 점을 제외하고는 다음과 String.prototype같은 함수 버전이 있습니다.

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

따라서 다음을 수행 할 수 있습니다.

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

그리고 다음과 같이 끝납니다.

[
  "<br />&dagger; bbbb",
  "<br />&Dagger; cccc"
]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.