如何在一场比赛中进入比赛? [英] How do I access the captures within a match?
问题描述
我正在尝试解析一个csv文件,并且我试图在Perl6的原始正则表达式中访问名称正则表达式.原来是零.正确的方法是什么?
I am trying to parse a csv file, and I am trying to access names regex in proto regex in Perl6. It turns out to be Nil. What is the proper way to do it?
grammar rsCSV {
regex TOP { ( \s* <oneCSV> \s* \, \s* )* }
proto regex oneCSV {*}
regex oneCSV:sym<noQuote> { <-[\"]>*? }
regex oneCSV:sym<quoted> { \" .*? \" } # use non-greedy match
}
my $input = prompt("Enter csv line: ");
my $m1 = rsCSV.parse($input);
say "===========================";
say $m1;
say "===========================";
say "1 " ~ $m1<oneCSV><quoted>; # this fails; it is "Nil"
say "2 " ~ $m1[0];
say "3 " ~ $m1[0][2];
推荐答案
详细讨论补充了克里斯托夫的答案
我正在尝试解析一个csv文件
I am trying to parse a csv file
也许您专注于学习Perl 6解析并且正在编写一些一次性的代码.但是,如果要开箱即用地分析工业强度CSV,请注意Text :: CSV模块 [1] .
Perhaps you are focused on learning Perl 6 parsing and are writing some throwaway code. But if you want industrial strength CSV parsing out of the box, please be aware of the Text::CSV modules[1].
我正在尝试访问一个命名的正则表达式
I am trying to access a named regex
如果您正在学习Perl 6解析,请注意jnthn的语法跟踪器和调试器 [2] .
If you are learning Perl 6 parsing, please be aware of jnthn's grammar tracer and debugger[2].
在Perl6中的原始正则表达式中
in proto regex in Perl6
您的问题与原始正则表达式无关.
Your issue is unrelated to it being a proto regex.
问题在于,虽然与您命名的捕获相对应的匹配对象存储在$m1
中的总体匹配对象中,但它并没有精确地存储在您要查找的位置
Instead the issue is that, while the match object corresponding to your named capture is stored in the overall match object you stored in $m1
, it is not stored precisely where you are looking for it.
要查看发生了什么,我将首先模拟您要尝试执行的操作.我将使用仅声明一个捕获的正则表达式,即与字符串ab
匹配的命名"(也称为关联")捕获.
To see what's going on, I'll start by simulating what you were trying to do. I'll use a regex that declares just one capture, a "named" (aka "Associative") capture that matches the string ab
.
given 'ab'
{
my $m1 = m/ $<named-capture> = ( ab ) /;
say $m1<named-capture>;
# 「ab」
}
与命名捕获相对应的匹配对象存储在您可能希望它出现在$m1
中的$m1<named-capture>
处的位置.
The match object corresponding to the named capture is stored where you'd presumably expect it to appear within $m1
, at $m1<named-capture>
.
但是使用$m1<oneCSV>
却得到了Nil.有什么作用?
But you were getting Nil with $m1<oneCSV>
. What gives?
捕获有两种类型:命名(又名关联")和编号(又名位置").您在正则表达式中写的包围<oneCSV>
的括号引入了 numbered 捕获:
There are two types of capture: named (aka "Associative") and numbered (aka "Positional"). The parens you wrote in your regex that surrounded <oneCSV>
introduced a numbered capture:
given 'ab'
{
my $m1 = m/ ( $<named-capture> = ( ab ) ) /; # extra parens added
say $m1[0]<named-capture>;
# 「ab」
}
/ ( ... ) /
中的括号声明单个顶级编号的捕获.如果匹配,则相应的匹配对象存储在$m1[0]
中. (如果您的正则表达式看起来像/ ... ( ... ) ... ( ... ) ... ( ... ) ... /
,则与第二对括号匹配的另一个匹配对象将存储在$m1[1]
中,另一个存储在$m1[2]
中,用于第三对括号,依此类推.)
The parens in / ( ... ) /
declare a single top level numbered capture. If it matches, then the corresponding match object is stored in $m1[0]
. (If your regex looked like / ... ( ... ) ... ( ... ) ... ( ... ) ... /
then another match object corresponding to what matches the second pair of parentheses would be stored in $m1[1]
, another in $m1[2]
for the third, and so on.)
然后将$<named-capture> = ( ab )
的匹配结果存储在内部 $m1[0]
中.这就是say $m1[0]<named-capture>
起作用的原因.
The match result for $<named-capture> = ( ab )
is then stored inside $m1[0]
. That's why say $m1[0]<named-capture>
works.
到目前为止,一切都很好.但这只是故事的一半...
So far so good. But this is only half the story...
在紧接上面的代码中的$m1[0]<named-capture>
工作时,在原始代码的$m1[0]<oneCSV>
中,您仍然仍然无法获得匹配对象.这是因为您还使用了*
量化器:
While $m1[0]<named-capture>
in the immediately above code is working, you would still not get a match object in $m1[0]<oneCSV>
in your original code. This is because you also asked for multiple matches of the zeroth capture because you used a *
quantifier:
given 'ab'
{
my $m1 = m/ ( $<named-capture> = ( ab ) )* /; # * is a quantifier
say $m1[0][0]<named-capture>;
# 「ab」
}
由于*
量词要求进行多次匹配,因此Perl 6将匹配对象的列表写入$m1[0]
中. (在这种情况下,只有这样一个匹配项,因此您最终得到一个长度为1的列表,即仅$m1[0][0]
(而不是$m1[0][1]
,$m1[0][2]
等).)
Because the *
quantifier asks for multiple matches, Perl 6 writes a list of match objects into $m1[0]
. (In this case there's only one such match so you end up with a list of length 1, i.e. just $m1[0][0]
(and not $m1[0][1]
, $m1[0][2]
, etc.).)
-
捕获巢;
captures nest;
由*
或+
量化的捕获对应于两个嵌套级别,而不仅仅是一个.
a capture quantified by either *
or +
corresponds to two levels of nesting not just one.
在原始代码中,您必须编写say $m1[0][0]<oneCSV>;
才能找到所需的匹配对象.
In your original code, you'd have to write say $m1[0][0]<oneCSV>;
to get to the match object you're looking for.
[1] 安装相关模块,并在代码开始处编写use Text::CSV;
(用于纯Perl 6实现)或use Text::CSV:from<Perl5>;
(用于Perl 5 plus XS实现). (对话幻灯片(单击顶部的单词,例如"csv",以浏览幻灯片), 视频, Perl 6模块, Perl 5 XS模块.)
[1] Install relevant modules and write use Text::CSV;
(for a pure Perl 6 implementation) or use Text::CSV:from<Perl5>;
(for a Perl 5 plus XS implementation) at the start of your code. (talk slides (click on top word, eg. "csv", to advance through slides), video, Perl 6 module, Perl 5 XS module.)
[2] 安装相关模块,并在代码的开头写入use Grammar::Tracer;
或use Grammar::Debugger;
. (幻灯片,模块.)
[2] Install relevant modules and write use Grammar::Tracer;
or use Grammar::Debugger;
at the start of your code`. (talk slides, video, modules.)
这篇关于如何在一场比赛中进入比赛?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!