JavaScript 正则表达式在组合正则表达式时添加受保护的模式

JavaScript regex add protected patterns when combining regex

要在 JavaScript 中组合一个或多个正则表达式模式,我正在使用以下函数:

Tokenizer.prototype.combinePatterns = function() {
  return new RegExp('(' + [].slice.call(arguments).map(function (e) {
      var e = e.toString()
      return '(?:' + e.substring(1, e.length - 1) + ')'
  }).join('|') + ')', "gi")
};

这很好用。现在我想“保护”一些模式,这意味着我想在执行生成的正则表达式时排除一些模式。这意味着我希望 default_pattern 不应用于 protected_patterns 数组中定义的任何模式(这个概念取自 MOSES Tokenizer protected patterns 选项)。

这些受保护的模式可能会或不会在默认模式中定义:

AggressiveTokenizer.prototype.tokenize = function(text, params = {}) {
    var options = {
        default_pattern: /[^a-z0-9äâàéèëêïîöôùüûœç]+/,
        protected_patterns: []
    };
    for (var attr in params) options[attr] = params[attr];
    var patterns = [].concat(options.protected_patterns).concat(options.default_pattern);
    // LP: pass along all regex patterns as argument
    patterns = this.combinePatterns.apply(this,patterns);
    // break a string up into an array of tokens by anything non-word
    return this.trim(text.split(patterns));

};

按照这种方法,假设要保护一些模式,例如

[ '\bla([- ]?la)+\b']

我从 combinePatterns 方法的结果中得到这个组合正则表达式:

/((?:la([- ]?la)+)|(?:[^a-z0-9äâàéèëêïîöôùüûœç]+))/gi

结果与预期不符,因此在具有 salut comment allez-vous la-la-la 的(法语)文本中举例说明,虽然我得到了所需的 la-la-la 令牌作为一个整体,但我得到了 undefined 标记,还有一个 la-

var combinePatterns = function() {
  return new RegExp('(' + [].slice.call(arguments).map(function(e) {
    var e = e.toString()
    return '(?:' + e.substring(1, e.length - 1) + ')'
  }).join('|') + ')', "gi")
};

var tokenize = function(text, params = {}) {
  var options = {
    default_pattern: /[^a-z0-9äâàéèëêïîöôùüûœç]+/,
    protected_patterns: []
  };
  for (var attr in params) options[attr] = params[attr];
  var patterns = [].concat(options.protected_patterns).concat(options.default_pattern);
  // LP: pass along all regex patterns as argument
  patterns = this.combinePatterns.apply(this, patterns);
  // break a string up into an array of tokens by anything non-word
  return text.trim().split(patterns);

}

var text = "salut comment allez-vous la-la-la";
var res = tokenize(text, {
  protected_patterns: ['\bla([- ]?la)+\b']
})
console.log(res)

我的预期结果应该是

[
  "salut",
  "comment"
  "allez"
  "vous"
  "la-la-la"
]

有什么问题:protected_patterns 数组中的受保护模式组合方法或正则表达式?

提示: 我注意到,combinePatterns 如果仅应用于 default_pattern 生成此正则表达式

return this.trim(text.split(/((?:[^a-z0-9äâàéèëêïîöôùüûœç]+))/gi));

这略微改变了默认模式的结果标记:

return this.trim(text.split(/[^a-z0-9äâàéèëêïîöôùüûœç]+/i));

let tokenize = function( str, preserve ) {
    const separators = /[^a-z0-9äâàéèëêïîöôùüûœç]+/i;
    // Convert the array of preserved patterns into one RegExp:
    const screen = new RegExp( '(?:' + preserve.map( s => '(?:' + s + ')' ).join( '|' ) + ')' );
    // Screening delimiter. Must not be split by separators:
    const scr = 'SSS';
    // Regular expression for unscreening:
    const scr_regex = new RegExp( scr + '(\d)' + scr );
    // Initialise the array of preserved substrings:
    let screened = [];
    return str
    // Temporarily screen preserved patterns:
    .replace( screen, s => scr + (screened.push( s ) - 1) + scr )
    // Split into tokens:
    .split( separators )
    // Restore screened substrings in each token:
    .map( s => s.replace( scr_regex, (_, i) => screened[parseInt( i )] ) );
};
let text = 'salut comment allez-vous la-la-la';
let res = tokenize( text, ['\bla(?:[- ]?la)+\b'] );
console.log( res );