正则表达式组不排除点

时间:2019-03-13 16:04:33

标签: javascript regex

假设我有以下字符串: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"]

以为分组可以解决我的问题,但所有匹配项也都包含点。

6 个答案:

答案 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件)。

有很多解决方案:

  1. 在指出自己的时候使用 LookBehind 断言。

  2. 修正每个结果,以后添加.map(x=>x.replace(/^\./, ""))

  3. 或者,如果您的输入结构不会比您提供的示例复杂得多,只需使用更便宜的方法即可:

    > 'div.classOneA.classOneB#idOne'.replace(/#.*/, "").split(".").slice(1)
    [ 'classOneA', 'classOneB' ]
    
  4. 使用.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)