我知道你一定听腻了:但你做错了。
我喜欢正则表达式,但它们并不是为此类问题而设计的。使用标准模板系统(如Template::Toolkit https://metacpan.org/pod/distribution/Template-Toolkit/lib/Template/Toolkit.pod.
如果您坚持这种方法,那么我建议您使用更简单的工具。不要尝试让正则表达式强制执行所有规则,而是尽可能使用最基本的正则表达式。在这种情况下,我建议您使用以下方法对文本进行标记split
:
use strict;
use warnings;
my $content = do {local $/; <DATA>};
my @tokens = split /(<!--(?:block:.*?|endblock)-->)/, $content;
use Data::Dump;
dd \@tokens;
__DATA__
some html content here top base
<!--block:first-->
some html content here 1 top
this <!--comment--> will make it fail here.
<!--block:second-->
some html content here 2 top
<!--block:third-->
some html content here 3a
some html content here 3b
<!--endblock-->
some html content here 2 bottom
<!--endblock-->
some html content here 1 bottom
<!--endblock-->
some html content here bottom base
Outputs:
[
"\nsome html content here top base\n",
"<!--block:first-->",
"\n some html content here 1 top\n this <!--comment--> will make it fail here.\n ",
"<!--block:second-->",
"\n some html content here 2 top\n ",
"<!--block:third-->",
"\n some html content here 3a\n some html content here 3b\n ",
"<!--endblock-->",
"\n some html content here 2 bottom\n ",
"<!--endblock-->",
"\n some html content here 1 bottom\n",
"<!--endblock-->",
"\nsome html content here bottom base",
]
正如您所看到的,该数组包含文本和匹配模式之一之间的交替。
现在,我不知道你的最终目标是什么,也不知道你最终想要什么格式的数据,所以我不能从这里提出任何建议。但是,如果原始数据结构确实满足您的需求,您可以很容易地重新创建它。更好的是,您实际上可以执行错误检查,以查找不匹配打开或关闭的块,而您的原始正则表达式会对您隐藏这些块。
Addendum
我已经在以下位置提供了这种方法的扩展完整解决方案:Perl replace nested blocks regular expression https://stackoverflow.com/a/24101864/1733163