Javascript 负前瞻正则表达式

Javascript 负前瞻正则表达式,javascript,regex,Javascript,Regex,我有这样一个字符串: <p>Year: ={year}</p>\ <p>Director: ={director}</p>\ <ul>@{actors}<li class="#{class}">={actor}</li>{actors}</ul>\ 有什么想法吗 编辑:我当前的解决方案是在@{}…{}中查找所有={match},并将=替换为类似=的内容。然后我抓取外面的,最后我回来,把带标记的放回原

我有这样一个字符串:

<p>Year: ={year}</p>\
<p>Director: ={director}</p>\
<ul>@{actors}<li class="#{class}">={actor}</li>{actors}</ul>\
有什么想法吗


编辑:我当前的解决方案是在
@{}…{}
中查找所有
={match}
,并将
=
替换为类似
=
的内容。然后我抓取外面的,最后我回来,把带标记的放回原来的状态。

在这里,你需要负向展望结尾
{whatever}

/(?!@.*)=\{([^{}]+)\}(?。*{[^{}]+\})/g

更新: Previous仅适用于每行的
{match}

挂接
@
实际上意味着一个LookBehind,在这种情况下很难使用LookBehind,因为LookBehind非常想知道要查找多少个字符

因此,让我们使用LookAhead进行前瞻:
=\{([^{}]+)\}(?![^@]*[^=@]{)
在末尾挂起
{tag}


编辑:demo

您可以使用正则表达式将字符串分解为段,如下所示:

var s = '<p>Year: ={year}</p> \
<p>Director: ={director}</p> \
<ul>@{actors}<li class="#{class}">={actor}</li>{actors}</ul>',
  re = /@\{([^}]+)\}(.*?)\{\1\}/g,
  start = 0,
  segments = [];

while (match = re.exec(s)) {
  if (match.index > start) {
    segments.push([start, match.index - start, true]);
  }
  segments.push([match.index, re.lastIndex - match.index, false]);
  start = re.lastIndex;
}

if (start < s.length) {
  segments.push([start, s.length - start, true]);
}

console.log(segments);
布尔值指示您是在-
true
-之外还是在
@{}…{}
段内。它使用反向引用将结束与开始匹配


然后,基于段,您可以按照正常方式执行替换。

这些
@{word}…{word}
构造是否可以嵌套?此外,在
{code>之前似乎有一些“特殊字符”,如
@
=
将其与结束标记区分开来。这些都是我们需要考虑的,还是还有其他需要考虑的?如果您可以使用
@{tag1}…={word}…@{tag2}…{tag2}…{tag1}
,那么你不能单独使用正则表达式。JavaScript正则表达式不支持任何类型的递归。@TimPietzcker:我对循环使用反向引用,
/{([^{}]+)\}(.+)\{\1\}/
,因此
{tag1}
将只匹配结束的
{tag1}
在该匹配中,我可以再次运行同一个正则表达式…好的,一个文档既不能包含
@{tag}…{tag}…{tag}
也不能包含
@{tag}…{tag tag}…@{tag}…{tag}
?@elclanrs:但是嵌套对象中的键可能会出现在不同的级别上。我认为正则表达式并不是最好的工具,您是否尝试过一个简单的基于堆栈的解析器?这只适用于示例,因为
={…}之间有一个换行符
tags。这个看起来不错,我要试试。@elclanrs-someas:)很高兴能帮上忙!
var s = '<p>Year: ={year}</p> \
<p>Director: ={director}</p> \
<ul>@{actors}<li class="#{class}">={actor}</li>{actors}</ul>',
  re = /@\{([^}]+)\}(.*?)\{\1\}/g,
  start = 0,
  segments = [];

while (match = re.exec(s)) {
  if (match.index > start) {
    segments.push([start, match.index - start, true]);
  }
  segments.push([match.index, re.lastIndex - match.index, false]);
  start = re.lastIndex;
}

if (start < s.length) {
  segments.push([start, s.length - start, true]);
}

console.log(segments);
[
    [0, 54, true], 
    [54, 51, false], 
    [105, 5, true]
]