JavaScript 动态正则表达式中所有格量词的替代方法
JavaScript Alternative To Possessive Quantifiers In Dynamic Regex
我正在使用 JavaScript 从逗号分隔的成员字符串中提取 "siblings" 的子集,我称之为 "generation" 字符串。
打个比方,成员都是同代人,但不都是手足(同父异母)。这是一个例子:
// 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 + ')(,)*)(.*)'; // Trouble is here
var mRegex = new RegExp(mPattern);
var mSiblings = generation.replace(mRegex, '');
上面确定的问题点涉及构造模式中的正则表达式量词。如上,全部设置为greedy,所以mSiblings的值为:
ACAD
这只是最后一个成员。将 mPattern 更改为不那么贪婪以期提取其他成员会产生以下结果
// Reluctant first expression yields ACAA
var mPattern = '(.*?)((' + mPattern + ')(,)*)(.*)';
// Reluctant last expression yields ACAD,AEAB,AEAD,AFAA
var mPattern = '(.*)((' + mPattern + ')(,)*)(.*?)';
// Reluctant first and last yields ACAA,ACAB,ACAD,AEAB,AEAD,AFAA
var mPattern = '(.*?)((' + mPattern + ')(,)*)(.*?)';
如果我能把中间的表达变成所有格,这个问题就解决了。像这样:
// Make as many "middle" matches as possible by changing (,)* to (,)*+
var mPattern = '(.*?)((' + mPattern + ')(,)*+)(.*?)';
但正如我所读(并且有语法错误可以证明),JavaScript 不支持所有格正则表达式量词。有人可以提出解决方案吗?谢谢你。
最明显的问题是</code>。在正则表达式中,您可以使用 <code>
而不是 </code> 来引用捕获组 #1。正则表达式中的 <code>(,)*
永远不会匹配任何内容。但是团体推荐无论如何也没有用。
当您在正则表达式中使用组引用时,您不会再次应用正则表达式的那部分,您只是匹配它第一次匹配的相同内容。也就是说,(ACA[A-Z])(,)*
将匹配 ACAA,ACAA
,但不会匹配 ACAA,ACAB
或 ACAA,ACAC
。如果你想这样做,你需要重复实际的正则表达式:(ACA[A-Z])(,ACA[A-Z])*
。由于您是动态生成正则表达式,所以这应该不是问题。
请注意,这是整个正则表达式:ACA[A-Z](,ACA[A-Z])*
。无需匹配您感兴趣的部分之前或之后的内容;这只会让工作变得更复杂(结果也更令人困惑)。您可以直接访问匹配结果,而不是使用那个 "replace" 噱头:
var match = mRegex.exec(generation);
if (match != null) {
mSiblings = match[0];
}
我正在使用 JavaScript 从逗号分隔的成员字符串中提取 "siblings" 的子集,我称之为 "generation" 字符串。
打个比方,成员都是同代人,但不都是手足(同父异母)。这是一个例子:
// 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 + ')(,)*)(.*)'; // Trouble is here
var mRegex = new RegExp(mPattern);
var mSiblings = generation.replace(mRegex, '');
上面确定的问题点涉及构造模式中的正则表达式量词。如上,全部设置为greedy,所以mSiblings的值为:
ACAD
这只是最后一个成员。将 mPattern 更改为不那么贪婪以期提取其他成员会产生以下结果
// Reluctant first expression yields ACAA
var mPattern = '(.*?)((' + mPattern + ')(,)*)(.*)';
// Reluctant last expression yields ACAD,AEAB,AEAD,AFAA
var mPattern = '(.*)((' + mPattern + ')(,)*)(.*?)';
// Reluctant first and last yields ACAA,ACAB,ACAD,AEAB,AEAD,AFAA
var mPattern = '(.*?)((' + mPattern + ')(,)*)(.*?)';
如果我能把中间的表达变成所有格,这个问题就解决了。像这样:
// Make as many "middle" matches as possible by changing (,)* to (,)*+
var mPattern = '(.*?)((' + mPattern + ')(,)*+)(.*?)';
但正如我所读(并且有语法错误可以证明),JavaScript 不支持所有格正则表达式量词。有人可以提出解决方案吗?谢谢你。
最明显的问题是</code>。在正则表达式中,您可以使用 <code>
而不是 </code> 来引用捕获组 #1。正则表达式中的 <code>(,)*
永远不会匹配任何内容。但是团体推荐无论如何也没有用。
当您在正则表达式中使用组引用时,您不会再次应用正则表达式的那部分,您只是匹配它第一次匹配的相同内容。也就是说,(ACA[A-Z])(,)*
将匹配 ACAA,ACAA
,但不会匹配 ACAA,ACAB
或 ACAA,ACAC
。如果你想这样做,你需要重复实际的正则表达式:(ACA[A-Z])(,ACA[A-Z])*
。由于您是动态生成正则表达式,所以这应该不是问题。
请注意,这是整个正则表达式:ACA[A-Z](,ACA[A-Z])*
。无需匹配您感兴趣的部分之前或之后的内容;这只会让工作变得更复杂(结果也更令人困惑)。您可以直接访问匹配结果,而不是使用那个 "replace" 噱头:
var match = mRegex.exec(generation);
if (match != null) {
mSiblings = match[0];
}