Perl6 语法:匹配整行
Perl6 grammars: match full line
我刚刚开始研究 perl6 语法。我怎样才能组成一个标记 "line" 来匹配一行开头和结尾之间的所有内容?我尝试了以下但没有成功:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP {
<line>
}
token line {
^^.*$$
}
}
my $match = sample.parse($txt);
say $match<line>[0];
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP { <line> }
token line { .* }
}
for $txt.lines -> $line {
## An single line of text....
say $line;
## Parse line of text to find match obj...
my $match = sample.parse($line);
say $match<line>;
}
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP {
<line>+
}
token line {
\N+ \n
}
}
my $match = sample.parse($txt);
say $match<line>[0];
或者,如果您可以具体说明该行:
grammar sample {
token TOP {
<line>+
}
rule line {
\w+ \d
}
}
我可以在此处的语法中看到 2 个问题,这里的第一个是标记行,^^ 和 $$ 是行开始和结束的锚点,但是您可以在它们之间添加新行。为了说明,我们只使用一个简单的正则表达式,先不使用语法:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
if $txt ~~ m/^^.*$$/ {
say "match";
say $/;
}
运行 即,输出为:
match
「row 1
row 2
row 3」
您看到正则表达式匹配得比预期的多,但是第一个问题不存在,这是因为棘轮,与令牌匹配将不起作用:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
my regex r {^^.*$$};
if $txt ~~ &r {
say "match regex";
say $/;
} else {
say "does not match regex";
}
my token t {^^.*$$};
if $txt ~~ &t {
say "match token";
say $/;
} else {
say "does not match token";
}
运行 即,输出为:
match regex
「row 1
row 2
row 3」
does not match token
我不太清楚为什么,但令牌和锚 $$ 似乎不能很好地协同工作。但是您想要的是搜索除换行符以外的所有内容,即 \N*
以下语法主要解决了您的问题:
grammar sample {
token TOP {<line>}
token line {\N+}
}
但是它只匹配第一次出现,因为你只搜索一行,你可能想要做的是搜索一行 + 一个可选的垂直空格(在你的情况下,你在末尾有一个新行你的字符串,但我猜你想取最后一行,即使末尾没有新行),重复几次:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP {[<line>\v?]*}
token line {\N+}
}
my $match = sample.parse($txt);
for $match<line> -> $l {
say $l;
}
该脚本的输出开始:
「row 1」
「row 2」
「row 3」
还可以帮助您使用和调试语法,2 个非常有用的模块:Grammar::Tracer 和 Grammar::Debugger。只需将它们包含在脚本的开头即可。 Tracer 会显示您的语法所完成的匹配的彩色树。调试器让你实时看到它一步步匹配。
您原来的方法可以通过
实现
grammar sample {
token TOP { <line>+ %% \n }
token line { ^^ .*? $$ }
}
就我个人而言,我不会尝试锚定 line
并使用 \N
代替,正如已经建议的那样。
我刚刚开始研究 perl6 语法。我怎样才能组成一个标记 "line" 来匹配一行开头和结尾之间的所有内容?我尝试了以下但没有成功:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP {
<line>
}
token line {
^^.*$$
}
}
my $match = sample.parse($txt);
say $match<line>[0];
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP { <line> }
token line { .* }
}
for $txt.lines -> $line {
## An single line of text....
say $line;
## Parse line of text to find match obj...
my $match = sample.parse($line);
say $match<line>;
}
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP {
<line>+
}
token line {
\N+ \n
}
}
my $match = sample.parse($txt);
say $match<line>[0];
或者,如果您可以具体说明该行:
grammar sample {
token TOP {
<line>+
}
rule line {
\w+ \d
}
}
我可以在此处的语法中看到 2 个问题,这里的第一个是标记行,^^ 和 $$ 是行开始和结束的锚点,但是您可以在它们之间添加新行。为了说明,我们只使用一个简单的正则表达式,先不使用语法:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
if $txt ~~ m/^^.*$$/ {
say "match";
say $/;
}
运行 即,输出为:
match
「row 1
row 2
row 3」
您看到正则表达式匹配得比预期的多,但是第一个问题不存在,这是因为棘轮,与令牌匹配将不起作用:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
my regex r {^^.*$$};
if $txt ~~ &r {
say "match regex";
say $/;
} else {
say "does not match regex";
}
my token t {^^.*$$};
if $txt ~~ &t {
say "match token";
say $/;
} else {
say "does not match token";
}
运行 即,输出为:
match regex
「row 1
row 2
row 3」
does not match token
我不太清楚为什么,但令牌和锚 $$ 似乎不能很好地协同工作。但是您想要的是搜索除换行符以外的所有内容,即 \N* 以下语法主要解决了您的问题:
grammar sample {
token TOP {<line>}
token line {\N+}
}
但是它只匹配第一次出现,因为你只搜索一行,你可能想要做的是搜索一行 + 一个可选的垂直空格(在你的情况下,你在末尾有一个新行你的字符串,但我猜你想取最后一行,即使末尾没有新行),重复几次:
my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS
grammar sample {
token TOP {[<line>\v?]*}
token line {\N+}
}
my $match = sample.parse($txt);
for $match<line> -> $l {
say $l;
}
该脚本的输出开始:
「row 1」
「row 2」
「row 3」
还可以帮助您使用和调试语法,2 个非常有用的模块:Grammar::Tracer 和 Grammar::Debugger。只需将它们包含在脚本的开头即可。 Tracer 会显示您的语法所完成的匹配的彩色树。调试器让你实时看到它一步步匹配。
您原来的方法可以通过
实现grammar sample {
token TOP { <line>+ %% \n }
token line { ^^ .*? $$ }
}
就我个人而言,我不会尝试锚定 line
并使用 \N
代替,正如已经建议的那样。