2012-03-24 147 views
2

的陣列中的給定像在JavaScript以下分割字符串,但保留分隔符拆分

var a = 'hello world\n\nbye world\n\nfoo\nbar\n\nfoo\nbaz\n\n'; 

我想把它分成數組這樣

['hello world', '\n\n', 'bye world', '\n\n', 'foo\nbar', '\n\n', 'foo\nbaz', '\n\n']. 

如果輸入var a = 'hello world\n\nbye world'字符串,結果應該是['hello world', '\n\n', 'bye world']

換句話說,我想將'\ n \ n'周圍的字符串拆分成一個數組,這樣數組也包含'\ n \ n'。有沒有什麼好辦法在JavaScript中做到這一點?

+0

你想要什麼''\ n \ n \ n \ nb''拆分成什麼? – Cameron 2012-03-24 19:24:52

+0

@AdamZalcman我已經嘗試在字符串上運行一個循環,並使用'indexOf'和'substr'函數來提取我想要的東西,但是我想知道是否有更好的方法來解決這個問題。 – 2012-03-24 19:27:20

+0

@Cameron對我來說,兩者都不錯:['a','\ n \ n','b']和['a','\ n \ n','\ n \ n','b 「]。這個輸出對於我的特殊情況來說並不重要,所以我們可以選擇哪個導致更優雅的代碼。 – 2012-03-24 19:29:28

回答

3

這裏是一個班輪:

str.match(/\n\n|(?:[^\n]|\n(?!\n))+/g) 

下面是它如何工作的:

  • \n\n兩個連續的換行字符匹配
  • (?:[^\n]|\n(?!\n))+比賽要麼
      的一個或多個字符的任意序列
    • [^\n]不是換行符,或
    • \n(?!\n)換行符但前提是不能再接再換行符

這種遞歸模式可以在任何長度適用於:

// useful function to quote strings for literal match in regular expressions 
RegExp.quote = RegExp.quote || function(str) { 
    return (str+"").replace(/(?=[.?*+^$[\]\\(){}|-])/g, "\\"); 
}; 
// helper function to build the above pattern recursively 
function buildRecursivePattern(chars, i) { 
    var c = RegExp.quote(chars[i]); 
    if (i < chars.length-1) return "(?:[^" + c + "]|" + c + buildRecursivePattern(chars, i+1) + ")"; 
    else return "(?!" + c + ")"; 
} 
function buildPattern(str) { 
    return RegExp(RegExp.quote(delimiter) + "|" + buildRecursivePattern(delimiter.match(/[^]/g), 0) + "+", "g"); 
} 

var str = 'hello world\n\nbye world\n\nfoo\nbar\n\nfoo\nbaz\n\n', 
    delimiter = "\n\n", 
    parts; 
parts = str.match(buildPattern(delimiter)) 

更新這裏有一個String.prototype.split的修改應該添加包含匹配分隔符的功能:

if ("a".split(/(a)/).length !== 3) { 
    (function() { 
     var _f = String.prototype.split; 
     String.prototype.split = function(separator, limit) { 
      if (separator instanceof RegExp) { 
       var re = new RegExp(re.source, "g"+(re.ignoreCase?"i":"")+(re.multiline?"m":"")), 
        match, result = [], counter = 0, lastIndex = 0; 
       while ((match = re.exec(this)) !== null) { 
        result.push(this.substr(lastIndex, match.index-lastIndex)); 
        if (match.length > 1) result.push(match[1]); 
        lastIndex = match.index + match[0].length; 
        if (++counter === limit) break; 
       } 
       result.push(this.substr(lastIndex)); 
       return result; 
      } else { 
       return _f.apply(arguments); 
      } 
     } 
    })(); 
} 
+2

+ 1000你的正則表達式mojo是強大的,sensei。對於我們這些凡人來說,正則表達式的細分如何? – 2012-03-24 19:57:32

+0

應該將'buildPattern'中的'build()'調用改爲'buildRecursivePattern'嗎? – 2012-03-24 22:02:54