尝试匹配JavaScript字符串上的所有正则表达式

时间:2019-06-17 18:43:59

标签: javascript regex

我正在尝试string.matchAll以下字符串:

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'

我要匹配以下内容:

  • 第一名:"textA [aaa](bbb)"
  • 第二名:" textB [ccc](ddd)"
  • 第3名:" textC"

注意:捕获组已经存在于regex中。这就是我所需要的。

它几乎可以正常工作,但是到目前为止,我还没有想到一种匹配字符串的最后部分的方法,该部分只是" textC",并且没有[*](*)模式。 / p>

我在做什么错了?

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'
const regexp = /(.*?)\[(.+?)\]\((.+?)\)/g;

const array = Array.from(text.matchAll(regexp));
console.log(JSON.stringify(array[0][0]));
console.log(JSON.stringify(array[1][0]));
console.log(JSON.stringify(array[2][0]));

更新:

除了以下答案中提供的好的解决方案外,这也是一种选择:

const text= 'textA [aaa](bbb) textB [ccc](ddd) textC'

const regexp = /(?!$)([^[]*)(?:\[(.*?)\]\((.*?)\))?/gm;

const array = Array.from(text.matchAll(regexp));

console.log(array);

3 个答案:

答案 0 :(得分:3)

这是因为没有第三场比赛。在前两个匹配之后,字符串中剩下的唯一内容是“文本C”:

https://regex101.com/r/H9Kn0G/1/

要解决此问题,请将整个第二部分设为可选(另请注意,以开头的\w而非.可以防止该点占用整个字符串以及使用的“仅分组”括号包围可选部分,以使您的匹配组保持相同):

(\w+)(?:\s\[(.+?)\]\((.+?)\))?

https://regex101.com/r/Smo1y1/2/

答案 1 :(得分:2)

解决方案1:通过匹配拆分

您可以通过匹配模式并从上一个索引到匹配结束获取子字符串来进行拆分:

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'
const regexp = /\[[^\][]*\]\([^()]*\)/g;
let m, idx = 0, result=[];
while(m=regexp.exec(text)) {
  result.push(text.substring(idx, m.index + m[0].length).trim());
  idx = m.index + m[0].length;
}
if (idx < text.length) {
  result.push(text.substring(idx, text.length).trim())
}
console.log(result);

注意:

  • \[[^\][]*\]\([^()]*\)匹配[[](带有[^\][]*)之外的任何0+个字符,然后是](,然后是0 +除()(带有[^()]*)之外的其他字符,然后是)(请参阅regex demo
  • 已删除捕获组,但是您可以还原它们并根据需要将其分别保存在结果数组中(或保存在另一个数组中)
  • .trim()被添加以消除前导/尾随空格(如有必要,请删除)。

解决方案2:匹配可选模式

这个想法是先在您拥有的模式之前匹配所有字符,然后再匹配您的模式或字符串结尾:

let result = text.match(/(?!$)(.*?)(?:\[(.*?)\]\((.*?)\)|$)/g);

如果字符串可以有换行符,请将.替换为[\s\S],或考虑以下模式:

let result = text.match(/(?!$)([\s\S]*?)(?:\[([^\][]*)\]\(([^()]*)\)|$)/g);

请参见the regex demo

JS演示:

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'
const regexp = /(?!$)(.*?)(?:\[(.*?)\]\((.*?)\)|$)/g;

const array = Array.from(text.matchAll(regexp));
console.log(JSON.stringify(array[0][0]));
console.log(JSON.stringify(array[1][0]));
console.log(JSON.stringify(array[2][0]));

正则表达式详细信息

  • (?!$)-不在字符串末尾
  • (.*?)-第1组:除换行符以外的任何0+个字符,应尽可能少(如果可以换行,请更改为[\s\S]*?或添加s修饰符,因为您定位了ECMAScript 2018)
  • (?:\[(.*?)\]\((.*?)\)|$)-两种选择之一:
    • \[(.*?)\]\((.*?)\)-[,第2组:除换行符以外的任何0+个字符,尽可能少; ](,第3组:除换行符以外的任何0+个字符尽量少用一个)
    • |-或
    • $-字符串的结尾。

答案 2 :(得分:0)

这就是我最终使用的:

const text= 'textA [aaa](bbb) textB [ccc](ddd) textC'

const regexp = /(?!$)([^[]*)(?:\[(.*?)\]\((.*?)\))?/gm;

const array = Array.from(text.matchAll(regexp));

console.log(array);