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

问题描述 投票:0回答:1

我正在尝试创建一个正则表达式模式,以匹配我正在构建的小应用程序的“虚假”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],因为与生成我试图在此步骤中提取的文本的另一个函数冲突。

编辑:一个打击我的想法是让第三个捕获组捕获并推送到列表阵列,但我不确定这是否会在现实中起作用?到目前为止我还没有工作

javascript arrays json regex
1个回答
0
投票

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

然而,我会寻求一个不同的解决方案:

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

要使用它,你需要有一个XML格式的字符串,所以除非你想使用<p>样式的标签,你首先必须将你的字符串转换为该字符串,确保使用<的内容需要获得&lt;

此外,{img}标签需要得到一个结束标记而不是括号。因此,对于该特定情况需要替换。

一旦完成,就可以直接从该XML获取DOM,这可能已经足够您使用了,但是可以通过简单的递归函数将其简化为您想要的结构:

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元素也表示为{ li: "...." }对象。

© www.soinside.com 2019 - 2024. All rights reserved.