JavaScript替代动态正则表达式中的占有量词

时间:2015-08-14 21:12:59

标签: javascript regex pattern-matching reluctant-quantifiers

我正在使用JavaScript从逗号分隔的成员字符串中提取“兄弟姐妹”的子集,我将其称为“生成”字符串。

隐喻地说,成员都来自同一代,但他们不是所有兄弟姐妹(来自同一个父母)。这是一个例子:

// This is the generation string to search
var generation  = 'ABAA,ABAB,ABAC,ABAD,ABBA,ACAA,ACAB,ACAD,AEAB,AEAD,AFAA';

// This is the member for whom to extract siblings (member included)
var member      = 'ACAA';

生成字符串及其成员具有以下特征:

  • 每个成员的字符数与其他成员相同
  • 字符串的所有成员都按字母顺序排序
  • 每组兄弟姐妹都会彼此相邻
  • 兄弟姐妹是那些除了最后一个字母
  • 之外共享相同字母组合的成员

继续这个例子......

// This is how I go about extracting the desired result: ACAA,ACAB,ACAD
var mParent     = member.substr(0, member.length - 1) ;
var mPattern    = mParent + '[A-Z]';
var mPattern    = '(.*)((' + mPattern + ')(,$1)*)(.*)'; // Trouble is here
var mRegex      = new RegExp(mPattern);
var mSiblings   = generation.replace(mRegex, '$2');

上面提到的故障点涉及构建模式中的正则表达式量词。如上所述,所有内容都设置为贪婪,因此mSiblings的值为:

ACAD

那只是最后一个成员。为了提取其他成员,将mPattern更改为不那么贪婪会产生以下结果

// Reluctant first expression yields ACAA
var mPattern = '(.*?)((' + mPattern + ')(,$1)*)(.*)'; 

// Reluctant last expression yields ACAD,AEAB,AEAD,AFAA
var mPattern = '(.*)((' + mPattern + ')(,$1)*)(.*?)'; 

// Reluctant first and last yields ACAA,ACAB,ACAD,AEAB,AEAD,AFAA
var mPattern = '(.*?)((' + mPattern + ')(,$1)*)(.*?)';

如果我可以使中间表达占有欲,这将是问题解决。像这样:

// Make as many "middle" matches as possible by changing (,$1)* to (,$1)*+
var mPattern = '(.*?)((' + mPattern + ')(,$1)*+)(.*?)';

但是正如我已经阅读过(并且有语法错误来证明它),JavaScript不支持所有格正则表达式量词。有人可以提出解决方案吗?谢谢。

1 个答案:

答案 0 :(得分:1)

最明显的问题是$1。在正则表达式中,您将引用使用\1而非$1捕获组#1。你的正则表达式中的(,$1)*永远不会匹配任何东西。但是,无论如何,小组参考都不会有任何好处。

当你在正则表达式中使用组引用时,你不会再次应用正则表达式的那部分,你只是简单地匹配它第一次匹配的那个东西。也就是说,(ACA[A-Z])(,\1)*将与ACAA,ACAA匹配,但不会与ACAA,ACABACAA,ACAC匹配。如果你想这样做,你需要重复实际的正则表达式:(ACA[A-Z])(,ACA[A-Z])*。由于您动态生成正则表达式,因此不应该成为问题。

请注意,这是整个正则表达式:ACA[A-Z](,ACA[A-Z])*。没有必要匹配您感兴趣的部分之前或之后的内容;这使得工作变得更加复杂(结果更加混乱)。您可以直接访问匹配结果,而不是使用"替换"手法:

var match = mRegex.exec(generation);
if (match != null) {
    mSiblings = match[0];
}