我正在尝试为Perl编写Mustache的分词器。我可以轻松处理大多数这样的标记:
但是我在Set Delimiters指令方面遇到了麻烦:
它运行良好,但Set Delimiters指令的目的是更改定界符,因此代码最终会看起来像这样。
而且说
#!/usr/bin/perl
use strict;
use warnings;
my $comment = qr/ \G \{\{ ! (?<comment> .+? ) }} /xs;
my $variable = qr/ \G \{\{ (?<variable> .+? ) }} /xs;
my $text = qr/ \G (?<text> .+? ) (?= \{\{ | \z ) /xs;
my $tokens = qr/ $comment | $variable | $text /x;
my $s = do { local $/; <DATA> };
while ($s =~ /$tokens/g) {
my ($type) = keys %+;
(my $contents = $+{$type}) =~ s/\n/\\n/;
print "type [$type] contents [$contents]\n";
}
__DATA__
{{!this is a comment}}
Hi {{name}}, I like {{thing}}.
但是我在Set Delimiters指令方面遇到了麻烦:
#!/usr/bin/perl
use strict;
use warnings;
my $delimiters = qr/ \G \{\{ (?<start> .+? ) = [ ] = (?<end> .+?) }} /xs;
my $comment = qr/ \G \{\{ ! (?<comment> .+? ) }} /xs;
my $variable = qr/ \G \{\{ (?<variable> .+? ) }} /xs;
my $text = qr/ \G (?<text> .+? ) (?= \{\{ | \z ) /xs;
my $tokens = qr/ $comment | $delimiters | $variable | $text /x;
my $s = do { local $/; <DATA> };
while ($s =~ /$tokens/g) {
for my $type (keys %+) {
(my $contents = $+{$type}) =~ s/\n/\\n/;
print "type [$type] contents [$contents]\n";
}
}
__DATA__
{{!this is a comment}}
Hi {{name}}, I like {{thing}}.
{{(= =)}}
如果我把它改成
my $delimiters = qr/ \G \{\{ (?<start> [^{]+? ) = [ ] = (?<end> .+?) }} /xs;
它运行良好,但Set Delimiters指令的目的是更改定界符,因此代码最终会看起来像这样。
my $variable = qr/ \G $start (?<variable> .+? ) $end /xs;
而且说
{{{== ==}}}
是完全有效的(即将定界符更改为{=
和=}
)。我想要但可能不需要的是能够说类似于(?:not starting string)+?
这样的内容。我觉得我只需要放弃对其进行清洁处理并将代码放入正则表达式中以强制它仅匹配我想要的内容。我试图避免这种情况,有四个原因:
- 我认为这样做不太干净。
- 它被标记为实验性的。
- 我不太熟悉它(我认为它归结为
(?{CODE})
和返回特殊值)。 - 我希望有人知道我不熟悉的其他奇特功能,更适合这种情况(例如
(?(condition)yes-pattern|no-pattern)
)。
只为了让事情清楚(我希望如此),我正在尝试匹配一个恒定长度的起始分隔符,后跟允许匹配且不包含起始分隔符的最短字符串,后跟一个空格,后跟等号,后跟允许匹配并以结束分隔符结尾的最短字符串。
my $delimiters = qr/ \G \{\{ (?<start> .+?) = [ ] = (?<end> (?: . (?! }} ) )+? ) }} /xs;
,但是$delimiters
规则没有匹配(它最终进入了变量规则)。如果我正确理解逻辑的话,它应该是在说“匹配上次离开的位置,后跟 {{,然后是至少有一个字符允许匹配的最短字符串,后跟 "= =",然后是任何不跟随 }} 的字符一次或多次,后跟 }};然而,在"{{(= =)}}"
中,)后面跟着 },那怎么可能行得通呢? - Chas. Owensmy $delimiters = qr/ \G \{\{ (?<start> (?: . (?! }} ) )+? ) = [ ] = (?<end> .+? ) }} /xs;
代替。这将防止第一个.+?
跨越指令。谢谢。 - Chas. Owens(.(?!$end))+?
中的最后一个?
,因为它后面跟着$end
。 - Qtax