修改正则表达式模式以将嵌套标签捕获到对象数组中

时间:2019-03-19 18:41:29

标签: javascript arrays json regex

我正在尝试创建正则表达式模式,以匹配我正在构建的小型应用程序的“人造” html标记。

我创建了正则表达式来捕获{tag}brackets{/tag}中找到的匹配项,并将其输出到这样的对象数组中:

{
  {key : value}, 
  {key : value}
}

当前模式的代码:

let str = "{p}This is a paragraph{/p} {img}(path/to/image) {ul}{li}This is a list item{/li}{li}Another list item{/li}{/ul}";

let regex = /\{(\w+)}(?:\()?([^\{\)]+)(?:\{\/1})?/g;
let match;
let matches = [];

while (match = regex.exec(str)) {
    matches.push({ [match[1]]: match[2]})
}

console.log(matches)

Link to JSbin

我已经意识到,我还需要一种模式来捕获嵌套组,并将它们放入数组中-因此上述string的结果将是:

[
  {p : "This is a paragraph"},
  {img : "path/to/image"},
  {ul : ["This is a list item", "Another List item"]}
]

这里的想法是按顺序匹配每个标签,以便数组的索引与找到它们的顺序匹配(即,上面字符串中的第一段为array[0],依此类推)。

如果有人对我如何构建模式有什么投入,将不胜感激。 如果有什么不同,我将不会有超过1层的深层嵌套。

如果可以这样做,我可以灵活地为ul使用不同的标记,但是由于与生成我要提取的文本的另一个函数冲突,我不能使用方括号[text]这一步。

编辑:一个让我大吃一惊的想法是让第三个捕获组捕获并推送到列表数组,但是我不确定这在现实中是否可行?到目前为止,我还没有开始工作

1 个答案:

答案 0 :(得分:0)

JavaScript不支持正则表达式内的递归,否则这将是一个潜在的解决方案。

但是我会寻求其他解决方案:

您可以依靠DOMParser-在浏览器中可用,或者,如果您在Node上,则几个模块中都可以使用类似的功能。

要使用它,您需要一个XML格式的字符串,因此,除非要使用<p>样式的标签,否则首先必须将字符串转换为该字符串,并确保包含{{ 1}}则需要获取<

此外,&lt;标记将需要获得一个结束标记,而不是括号。因此,对于这种特殊情况,必须进行更换。

一旦这种方法不起作用,从该XML中获取DOM就很简单了,它可能已经足够您使用,但是可以通过简单的递归函数将其简化为所需的结构:

{img}

除了const str = "{p}This is a paragraph{/p} {img}(path/to/image) {ul}{li}This is a list item{/li}{li}Another list item{/li}{/ul}"; const xml = str.replace(/\{img\}\((.*?)\)/g, "{img}$1{/img}") .replace(/</g, "&lt;") .replace(/\{/g, "<").replace(/\}/g, ">"); const parser = new DOMParser(); const dom = parser.parseFromString("<root>" + xml + "</root>", "application/xml").firstChild; const parse = dom => dom.nodeType === 3 ? dom.nodeValue.trim() : { [dom.nodeName]: dom.children.length ? Array.from(dom.childNodes, parse).filter(Boolean) : dom.firstChild.nodeValue }; const result = parse(dom).root; console.log(result);元素也表示为li对象之外,输出几乎是您想要的。