当前位置:  开发笔记 > 编程语言 > 正文

Perl6语法:匹配实线

如何解决《Perl6语法:匹配实线》经验,为你挑选了2个好方法。

我刚刚开始探索perl6语法.如何组成一个标记"行",它匹配行的开头和结尾之间的所有内容?我试过以下但没有成功:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS


grammar sample {
    token TOP {
        
    }

    token line {
        ^^.*$$
    }
}

my $match = sample.parse($txt);

say $match[0];

Pierre VIGIE.. 11

我在这里可以看到你的语法中的2个问题,这里的第一个是令牌行,^^和$$是开始和结束的锚点,但你可以在它们之间有新的行.为了说明,我们先使用一个简单的正则表达式,而不使用Grammar:

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 {}
    token line {\N+}
}

但是它只匹配第一次出现,因为你只搜索一行,你可能想要做的是搜索一行+一个可选的垂直空格(在你的情况下,你的字符串末尾有一个新行,但是我想你想在最后一行采取最后一行,即使最后没有新行),重复几次:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS

grammar sample {
    token TOP {[\v?]*}
    token line {\N+}
}

my $match = sample.parse($txt);
for $match -> $l {
    say $l;
}

该脚本的输出开始:

?row 1?
?row 2?
?row 3?

还可以帮助您使用和调试语法,2个非常有用的模块:Grammar :: Tracer和Grammar :: Debugger.只需将它们包含在脚本的开头即可.Tracer展示了由您的语法完成的匹配的彩色树.调试器允许您实时地逐步查看它.



1> Pierre VIGIE..:

我在这里可以看到你的语法中的2个问题,这里的第一个是令牌行,^^和$$是开始和结束的锚点,但你可以在它们之间有新的行.为了说明,我们先使用一个简单的正则表达式,而不使用Grammar:

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 {}
    token line {\N+}
}

但是它只匹配第一次出现,因为你只搜索一行,你可能想要做的是搜索一行+一个可选的垂直空格(在你的情况下,你的字符串末尾有一个新行,但是我想你想在最后一行采取最后一行,即使最后没有新行),重复几次:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS

grammar sample {
    token TOP {[\v?]*}
    token line {\N+}
}

my $match = sample.parse($txt);
for $match -> $l {
    say $l;
}

该脚本的输出开始:

?row 1?
?row 2?
?row 3?

还可以帮助您使用和调试语法,2个非常有用的模块:Grammar :: Tracer和Grammar :: Debugger.只需将它们包含在脚本的开头即可.Tracer展示了由您的语法完成的匹配的彩色树.调试器允许您实时地逐步查看它.


读克里斯托夫的评论,我意识到为什么令牌和$$不能很好地运作.令牌不进行回溯跟踪(因为棘轮),因此在^^.*$$中.*正在捕获行的最后一行,而$$不再匹配.在chritoph评论中,.*?使.*非贪婪,所以$$可以匹配

2> Christoph..:

你原来的aproach可以通过工作

grammar sample {
    token TOP { + %% \n }
    token line { ^^ .*? $$ }
}

就个人而言,我不会尝试锚定line和使用,\N如已经建议的那样.

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有