简体   繁体   English

在旧的IE版本中,如何在String.split中使用捕获组?

[英]How to use a capture group with String.split in old IE versions?

var textt = "L'architecture du système d'information devient";
var pattern = "/(ARCH)/gi";
var array = textt.split(pattern);
console.log(array)

This results in: 结果是:

[
    L',
    itecture du système d'information devient
]

And the expected result was: 预期结果是:

[
    L',
    arch,
    itecture du système d'information devien
]

Another example 另一个例子

var textt = "ARCHIMAG";
var pattern = "/(ARCH)/gi";
var array = textt.split(pattern);
console.log(array)

Results in: 结果是:

[
    IMAG
]

and the expected was: 预期是:

[
    ARCH,
    IMAG
]

If you're OK with a feature test and function to replace a non–capturing split, try the following. 如果您可以使用功能测试和功能来替换非捕获拆分,请尝试以下操作。 It tests for support when the script is loaded and assigns an appropriate function to nonCaptureSplit , so the test is only done once. 它会在脚本加载时测试是否支持,并将适当的功能分配给nonCaptureSplit ,因此测试仅执行一次。

The pattern will need to be escaped if you are using anything other than alphabetic characters or numerals (eg if there is punctuation in the string). 如果您使用的不是字母字符或数字,则需要转义该模式(例如,如果字符串中有标点符号)。

Edited 编辑

Now does a completely manual split if lacking support for non-capture split. 如果不支持非捕获拆分,则现在执行完全手动拆分。

// Do case insensitive, non-capture split
var nonCaptureSplit = (function() {

  // Feature test for non-capturing split
  if ( 'ab'.split(/(a)/).length == 3) {
    return function (str, pattern) {
      var re = new RegExp('(' + pattern + ')','i');
      return str.split(re);
    };

  // Otherise, do it with a function
  } else {
    return function(str, pattern) {

      // Do case insensitive split
      var result = [];
      var ts = str.toLowerCase(); // copy of string in lower case
      var tp = pattern.toLowerCase();
      var first = true;

      while (ts.indexOf(tp) != -1) {
        var i = ts.indexOf(tp);

        // If first match is at the start, insert empty string + pattern
        // Trim pattern from front of temp strings
        if (i == 0 && first) {
          result.push('', pattern);
          ts = ts.substring(tp.length);
          str = str.substring(tp.length);

        // If match is at the end, append pattern and ''
        // Set temp string to '' (i.e. finished)
        } else if (i == ts.length - tp.length) {
          result.push(str.substr(0,i), pattern);
          ts = '';
          str = '';

        // Otherwise, append the next unmatched part
        // and pattern
        } else {
          result.push(str.substring(0,i), pattern);
          ts = ts.substring(i + pattern.length);
          str = str.substring(i + pattern.length);

        }
        first = false;
      }

      // Append remainder of string or '' if used, i.e. last match
      // must have been at end of string
      result.push( ts.length? str : '');

      return result;

    };
  }
}());

tests: 测试:

alert(nonCaptureSplit('wa', 'wa'));        // ,wa,
alert(nonCaptureSplit('qwqwaba', 'wa'));   // qwq,wa,ba
alert(nonCaptureSplit('qwqwaba', 'qw'));   // ,qw,,qw,aba
alert(nonCaptureSplit('qwqwaba', 'ba'));   // qwqwa,ba,
alert(nonCaptureSplit('baaqwqbawaba', 'ba')); // ,ba,aqwq,ba,wa,ba,

alert(nonCaptureSplit("L'architecture du système d'information devient", "ARCH"));
// L',arch,itecture du système d'information devient

alert(nonCaptureSplit("ARCHIMAG", "ARCH")); // ,ARCH,IMAG

It might be a bit inefficient for large strings with lots of matches, but only in browsers without support for non–capturing split. 对于具有大量匹配项的大字符串而言,这可能会有点效率低下,但仅在不支持非捕获拆分的浏览器中。 Test results matched in Safari and IE 6. Please test thoroughly and let me know if there are issues. 测试结果在Safari和IE 6中匹配。请进行彻底测试,并让我知道是否存在问题。

Oh, this isn't a general solution, but it should work for the limited cases similar to the OP. 哦,这不是一个通用的解决方案,但它应适用于类似于OP的有限情况。

If you are looking to get around known browser issues in String.prototype.split then you need to take a look at Steven Levithan's cross browser fixes And see his original post from back in 2007. This is also used in his XRegExp library . 如果您想解决String.prototype.split已知的浏览器问题,那么您需要看一下Steven Levithan的跨浏览器修复程序,并查看他在2007年的原始文章 。XRegExp库中也使用了该文章 It is also used in ES5 shim and probably others. 它也用于ES5填充程序 (可能还有其他)中。

/*!
 * Cross-Browser Split 1.1.1
 * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
 * Available under the MIT License
 * ECMAScript compliant, uniform cross-browser split method
 */

/**
 * Splits a string into an array of strings using a regex or string separator. Matches of the
 * separator are not included in the result array. However, if `separator` is a regex that contains
 * capturing groups, backreferences are spliced into the result each time `separator` is matched.
 * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
 * cross-browser.
 * @param {String} str String to split.
 * @param {RegExp|String} separator Regex or string to use for separating the string.
 * @param {Number} [limit] Maximum number of items to include in the result array.
 * @returns {Array} Array of substrings.
 * @example
 *
 * // Basic use
 * split('a b c d', ' ');
 * // -> ['a', 'b', 'c', 'd']
 *
 * // With limit
 * split('a b c d', ' ', 2);
 * // -> ['a', 'b']
 *
 * // Backreferences in result array
 * split('..word1 word2..', /([a-z]+)(\d+)/i);
 * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
 */
var split;

// Avoid running twice; that would break the `nativeSplit` reference
split = split || function (undef) {

    var nativeSplit = String.prototype.split,
        compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group
        self;

    self = function (str, separator, limit) {
        // If `separator` is not a regex, use `nativeSplit`
        if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
            return nativeSplit.call(str, separator, limit);
        }
        var output = [],
            flags = (separator.ignoreCase ? "i" : "") +
                    (separator.multiline  ? "m" : "") +
                    (separator.extended   ? "x" : "") + // Proposed for ES6
                    (separator.sticky     ? "y" : ""), // Firefox 3+
            lastLastIndex = 0,
            // Make `global` and avoid `lastIndex` issues by working with a copy
            separator = new RegExp(separator.source, flags + "g"),
            separator2, match, lastIndex, lastLength;
        str += ""; // Type-convert
        if (!compliantExecNpcg) {
            // Doesn't need flags gy, but they don't hurt
            separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
        }
        /* Values for `limit`, per the spec:
         * If undefined: 4294967295 // Math.pow(2, 32) - 1
         * If 0, Infinity, or NaN: 0
         * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
         * If negative number: 4294967296 - Math.floor(Math.abs(limit))
         * If other: Type-convert, then use the above rules
         */
        limit = limit === undef ?
            -1 >>> 0 : // Math.pow(2, 32) - 1
            limit >>> 0; // ToUint32(limit)
        while (match = separator.exec(str)) {
            // `separator.lastIndex` is not reliable cross-browser
            lastIndex = match.index + match[0].length;
            if (lastIndex > lastLastIndex) {
                output.push(str.slice(lastLastIndex, match.index));
                // Fix browsers whose `exec` methods don't consistently return `undefined` for
                // nonparticipating capturing groups
                if (!compliantExecNpcg && match.length > 1) {
                    match[0].replace(separator2, function () {
                        for (var i = 1; i < arguments.length - 2; i++) {
                            if (arguments[i] === undef) {
                                match[i] = undef;
                            }
                        }
                    });
                }
                if (match.length > 1 && match.index < str.length) {
                    Array.prototype.push.apply(output, match.slice(1));
                }
                lastLength = match[0].length;
                lastLastIndex = lastIndex;
                if (output.length >= limit) {
                    break;
                }
            }
            if (separator.lastIndex === match.index) {
                separator.lastIndex++; // Avoid an infinite loop
            }
        }
        if (lastLastIndex === str.length) {
            if (lastLength || !separator.test("")) {
                output.push("");
            }
        } else {
            output.push(str.slice(lastLastIndex));
        }
        return output.length > limit ? output.slice(0, limit) : output;
    };

    // For convenience
    String.prototype.split = function (separator, limit) {
        return self(this, separator, limit);
    };

    return self;

}();

this is the best solution: 这是最好的解决方案:

function ieSplit(str, separator) {
var match = str.match(RegExp(separator, 'g'));
var notmatch = str.replace(new RegExp(separator, 'g'), '[|]').split('[|]');
var merge = [];
for(i in notmatch) {
    merge.push(notmatch[i]);
    if (match != null && match[i] != undefined) {
        merge.push(match[i]);
    }
}
return merge;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM