拆分字符串,但保留拆分数组中的分隔符

Split strings but preserve delimiters in the array of splits

本文关键字:拆分 分隔符 数组 保留 字符串      更新时间:2023-09-26

在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中有什么巧妙的方法可以做到这一点吗?

这里有一行代码:

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