Regex 用于模板化子循环的递归正则表达式
所以我研究了递归正则表达式匹配的其他解决方案,但是我仍然没有得到一个合适的正则表达式匹配 我有一个我想自己解析的通用把手样式模板,一个带有标题的表:Regex 用于模板化子循环的递归正则表达式,regex,templates,recursion,Regex,Templates,Recursion,所以我研究了递归正则表达式匹配的其他解决方案,但是我仍然没有得到一个合适的正则表达式匹配 我有一个我想自己解析的通用把手样式模板,一个带有标题的表: <table> <thead> <tr> {{#each columns as col }}<th>{{col}}</th>{{/each}} </tr> </thead> <tb
<table>
<thead>
<tr>
{{#each columns as col }}<th>{{col}}</th>{{/each}}
</tr>
</thead>
<tbody>
{{#each rows as row }}
<tr>
{{#each row as col }}<td>col</td>{{/each}}
</tr>
{{/each}}
</tbody>
</table>
正则表达式很好地匹配了
中的{{{each columns…
,但它似乎忽略了{124;(?R)
部分,只匹配{{{each}行…
,直到第一个{/each}
。我当然希望它能够匹配内部和外部的#表达式。如何匹配?这可能比简单的嵌套括号复杂得多
(在遇到类似的事情之前,我一直觉得自己是RegEx的专业人士。我已经尝试了一段时间,regular-expressions.info让我更加困惑。)
我目前正在做{{{{each#u sub…}}{{/each#u sub}}}来解决这个问题
因此,我的正则表达式不会在第一个结束标记上停止,但这显然是一种次优的方法。我还有其他几个应用程序可以从递归正则表达式中受益,但无法找出我做错了什么。它并没有忽略递归,只是永远无法到达它。因为*?
能够匹配您的delimiters({{{each…}}
和{{/each}}
),它匹配它找到的第一个结束分隔符并报告成功,而不需要递归
要使此技术起作用,(?R)
前面的分支必须匹配任何非分隔符的内容。由于分隔符由多个字符组成,您不能像链接到的问题中那样使用否定字符类。相反,您需要使用:
(?:(?!{{[#/]每个\b)*
这与*
相同,只是在它使用每个字符之前,它会检查以确保它不是{{{each
或{/each
的开头。这里是上下文:
{{\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
如果第一个分支失败,则表示您遇到了类似于分隔符的问题。如果它是一个开始分隔符,则第二个分支将接管并尝试递归地匹配整个模式。否则,它将从循环中弹出(请注意组后面的*
,您也没有看到)并尝试匹配结束分隔符
虽然上面的正则表达式在有效输入上可以很好地工作,但如果输入格式不正确,它会遭受灾难性的回溯。为了避免这种情况,您可以使用替代选项(正如@Wiktor在其评论中所做的):
{{{each\s+(\w+)\s+as\s+(\w+)\s*}(?:(?!{{[}/]each\b)。*(?:(?:(?:(?:(?!{[}/]each\b)。*)*{{/each}
这是一个更具可读性的版本,添加了所有格量词,以挤出更多的速度:
{{\#每个\s+(\w+)\s+as\s+(\w+)\s*}
(?:(?!{{[#/]各\b)*+
(?:
(?R)
(?:(?!{{[#/]各\b)*+
)*+
{{/每个}}
它没有忽略递归,它只是永远不会到达它。因为*?
能够匹配您的分隔符({{{each…}}
和{/each}}
),它匹配它找到的第一个结束分隔符并报告成功,而不需要递归
要使此技术起作用,(?R)
前面的分支必须匹配任何非分隔符的内容。由于分隔符由多个字符组成,您不能像链接到的问题中那样使用否定字符类。相反,您需要使用:
(?:(?!{{[#/]每个\b)*
这与*
相同,只是在它使用每个字符之前,它会检查以确保它不是{{{each
或{/each
的开头。这里是上下文:
{{\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
如果第一个分支失败,则表示您遇到了类似于分隔符的问题。如果它是一个开始分隔符,则第二个分支将接管并尝试递归地匹配整个模式。否则,它将从循环中弹出(请注意组后面的*
,您也没有看到)并尝试匹配结束分隔符
虽然上面的正则表达式在有效输入上可以很好地工作,但如果输入格式不正确,它会遭受灾难性的回溯。为了避免这种情况,您可以使用替代选项(正如@Wiktor在其评论中所做的):
{{{each\s+(\w+)\s+as\s+(\w+)\s*}(?:(?!{{[}/]each\b)。*(?:(?:(?:(?:(?!{[}/]each\b)。*)*{{/each}
这是一个更具可读性的版本,添加了所有格量词,以挤出更多的速度:
{{\#每个\s+(\w+)\s+as\s+(\w+)\s*}
(?:(?!{{[#/]各\b)*+
(?:
(?R)
(?:(?!{{[#/]各\b)*+
)*+
{{/每个}}
[^()]*
在您链接到的正则表达式中,不表示前导边界或尾随边界。因此,您需要这样的东西。谢谢@WiktorStribiżew!这正是我想要的。[^()]*
在您链接到的正则表达式中,它不表示前导边界或尾随边界。因此,您需要这样的东西。谢谢@WiktorStribiżew!这正符合我的要求。哇,答案太棒了,我想我不会轻易发现这一点。它在我的应用程序中工作。我需要一点时间才能理解它的工作原理,但是您的answer是一个很好的资源。多亏了你和Wiktor!哇,答案太棒了,我想我不会轻易发现这个。它在我的应用程序中工作。我需要一点时间来理解它是如何工作的,但你的答案是一个很好的资源。多亏了你和Wiktor!