假设我有以下字符串:div.classOneA.classOneB#idOne
尝试编写一个正则表达式,从中提取类(classOneA,classOneB)。我只能使用Lookbehind assertion来执行此操作。
它看起来像这样:
'div.classOneA.classOneB#idOne'.match(/(?<=\.)([^.#]+)/g)
> (2) ["classOneA", "classOneB"]
现在,我想将其存档,而无需使用后面的方法,也不真正理解为什么我的解决方案无法正常工作。
'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/g)
> (2) [".classOneA", ".classOneB"]
以为分组可以解决我的问题,但所有匹配项也都包含点。
答案 0 :(得分:1)
在Javascript中,没有一个好的方法可以同时匹配多次(/ g选项)并拾取捕获组(在括号中)。试试这个:
var input = "div.classOneA.classOneB#idOne";
var regex = /\.([^.#]+)/g;
var matches, output = [];
while (matches = regex.exec(input)) {
output.push(matches[1]);
}
答案 1 :(得分:1)
这是因为使用g
修饰符可以获取所有匹配的子字符串,但不能获取其匹配的组(就像(...)
对像(?:...)
那样工作。
你知道。 Whithout g
修饰符:
> 'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/)
[ '.classOneA',
'classOneA',
index: 3,
input: 'div.classOneA.classOneB#idOne',
groups: undefined ]
使用g
修饰符:
> 'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/g)
[ '.classOneA', '.classOneB' ]
换句话说:您获得所有匹配项,但每次仅获得整个匹配项(0件)。
有很多解决方案:
在指出自己的时候使用 LookBehind 断言。
修正每个结果,以后添加.map(x=>x.replace(/^\./, ""))
或者,如果您的输入结构不会比您提供的示例复杂得多,只需使用更便宜的方法即可:
> 'div.classOneA.classOneB#idOne'.replace(/#.*/, "").split(".").slice(1)
[ 'classOneA', 'classOneB' ]
使用.replace()
+回调代替.match()
,以便能够访问每个匹配项的捕获组:
const str = 'div.classOneA.classOneB#idOne';
const matches = [];
str.replace(/\.([^.#]+)/g, (...args)=>matches.push(args[1]))
console.log(matches); // [ 'classOneA', 'classOneB' ]
我建议使用第三个(如果没有其他可能最终破坏它的输入),因为它效率更高(实际的正则表达式仅用于修剪'#idOne'部分)。
答案 2 :(得分:0)
如果您知道要搜索包含class
的文本,则可以使用类似
'div.classOneA.classOneB#idOne'.match(/class[^.#]+/g)
如果您唯一知道的是文本前面有一个点,那么您必须使用lookbehind。
答案 3 :(得分:0)
此正则表达式无需任何断言就可以工作:
'div.classOneA.classOneB#idOne'.match(/\.[^\.#]+/g).map(item => item.substring(1));
Lookbehind断言最近在JavaScript中不可用。
答案 4 :(得分:0)
如果要扩展正则表达式。您可以简单地map
处理结果并将.
替换为空字符串
let op = 'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/g)
.map(e=> e.replace(/\./g,''))
console.log(op)
答案 5 :(得分:0)
我不是使用正则表达式的专家-尤其是在Java语言中-但经过对MDN的研究后,我弄清楚了为什么您的尝试不起作用以及如何解决。
问题在于,将.match
与带有/g
标志will ignore capturing groups的正则表达式一起使用。因此,相反,您必须在regexp对象上使用.exec方法,并使用循环多次执行它以获取所有结果。
因此,以下代码有效,并且可以适用于类似情况。 (请注意grp[1]
-这是因为.exec
返回的数组的第一个元素是整个匹配项,组是后续的元素。)
var regExp = /\.([^.#]+)/g
var result = [];
var grp;
while ((grp = regExp.exec('div.classOneA.classOneB#idOne')) !== null) {
result.push(grp[1]);
}
console.log(result)