我如何访问比赛中的捕获?
How do I access the captures within a match?
我正在尝试解析一个 csv 文件,并且正在尝试访问 Perl6 中原始正则表达式中的名称正则表达式。结果是零。正确的做法是什么?
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];
<oneCSV>
的匹配位于捕获组的范围内,您可以通过 $m1[0]
.
获得该捕获组
由于组是用 *
量化的,结果将再次是一个列表,即您需要另一个索引操作来获取匹配对象,例如 $m1[0][0]
用于第一个。
然后可以通过名称访问命名的捕获,例如$m1[0][0]<oneCSV>
。这将已经包含 protoregex 适当分支的匹配结果。
如果您想要整个匹配列表而不是特定的匹配列表,您可以使用 >>
或 map
,例如 $m1[0]>>.<oneCSV>
.
补充 Christoph 回答的详细讨论
I am trying to parse a csv file
也许您正在专注于学习 Perl 6 解析并且正在编写一些一次性代码。但是如果你想要开箱即用的工业强度 CSV 解析,请注意 Text::CSV 模块[1].
I am trying to access a named regex
如果你正在学习Perl 6解析,请注意jnthn的语法跟踪器和调试器[2].
in proto regex in Perl6
您的问题与原始正则表达式无关。
相反,问题是,虽然与您命名的捕获 对应的匹配对象 存储在您存储在 $m1
中的整体匹配对象中,但它并未存储正是您要查找的位置。
捕获对应的匹配对象出现在哪里?
要了解发生了什么,我将从模拟您尝试执行的操作开始。我将使用一个只声明一个捕获的正则表达式,一个匹配字符串 ab
.
的“命名”(又名“关联”)捕获
given 'ab'
{
my $m1 = m/ $<named-capture> = ( ab ) /;
say $m1<named-capture>;
# 「ab」
}
与命名捕获对应的匹配对象存储在您可能希望它出现在 $m1
中的位置 $m1<named-capture>
。
但是 $m1<oneCSV>
你得到的是 Nil。给出了什么?
为什么你的 $m1<oneCSV>
不起作用
有两种捕获类型:命名(又名“关联”)和编号(又名“位置”)。您在 <oneCSV>
周围的正则表达式中编写的括号引入了 numbered 捕获:
given 'ab'
{
my $m1 = m/ ( $<named-capture> = ( ab ) ) /; # extra parens added
say $m1[0]<named-capture>;
# 「ab」
}
/ ( ... ) /
中的括号声明单个顶级编号捕获。如果匹配,则对应的匹配对象存储在$m1[0]
中。 (如果您的正则表达式看起来像 / ... ( ... ) ... ( ... ) ... ( ... ) ... /
,那么与匹配第二对括号的内容对应的另一个匹配对象将存储在 $m1[1]
中,另一个存储在 $m1[2]
中,以此类推。)
然后$<named-capture> = ( ab )
的匹配结果存储在里面$m1[0]
。这就是 say $m1[0]<named-capture>
起作用的原因。
到目前为止一切顺利。但这只是故事的一半...
为什么您的代码中的 $m1[0]<oneCSV>
也不起作用
虽然上面代码中的 $m1[0]<named-capture>
有效,但您 仍然 无法在原始代码中的 $m1[0]<oneCSV>
中获得匹配对象。这是因为您还要求第 0 次捕获的 多个匹配项 因为您使用了 *
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]
等)。)
总结
夺巢;
通过 *
或 +
量化的捕获对应于 两个 嵌套级别,而不仅仅是一个。
在您的原始代码中,您必须编写 say $m1[0][0]<oneCSV>;
才能找到您要查找的匹配对象。
[1] 安装相关模块并写入 use Text::CSV;
(对于纯 Perl 6 实现)或 use Text::CSV:from<Perl5>;
(对于 Perl 5 plus XS 实现) 在代码的开头。 (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;
。 (talk slides, video, modules.)
我正在尝试解析一个 csv 文件,并且正在尝试访问 Perl6 中原始正则表达式中的名称正则表达式。结果是零。正确的做法是什么?
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];
<oneCSV>
的匹配位于捕获组的范围内,您可以通过 $m1[0]
.
由于组是用 *
量化的,结果将再次是一个列表,即您需要另一个索引操作来获取匹配对象,例如 $m1[0][0]
用于第一个。
然后可以通过名称访问命名的捕获,例如$m1[0][0]<oneCSV>
。这将已经包含 protoregex 适当分支的匹配结果。
如果您想要整个匹配列表而不是特定的匹配列表,您可以使用 >>
或 map
,例如 $m1[0]>>.<oneCSV>
.
补充 Christoph 回答的详细讨论
I am trying to parse a csv file
也许您正在专注于学习 Perl 6 解析并且正在编写一些一次性代码。但是如果你想要开箱即用的工业强度 CSV 解析,请注意 Text::CSV 模块[1].
I am trying to access a named regex
如果你正在学习Perl 6解析,请注意jnthn的语法跟踪器和调试器[2].
in proto regex in Perl6
您的问题与原始正则表达式无关。
相反,问题是,虽然与您命名的捕获 对应的匹配对象 存储在您存储在 $m1
中的整体匹配对象中,但它并未存储正是您要查找的位置。
捕获对应的匹配对象出现在哪里?
要了解发生了什么,我将从模拟您尝试执行的操作开始。我将使用一个只声明一个捕获的正则表达式,一个匹配字符串 ab
.
given 'ab'
{
my $m1 = m/ $<named-capture> = ( ab ) /;
say $m1<named-capture>;
# 「ab」
}
与命名捕获对应的匹配对象存储在您可能希望它出现在 $m1
中的位置 $m1<named-capture>
。
但是 $m1<oneCSV>
你得到的是 Nil。给出了什么?
为什么你的 $m1<oneCSV>
不起作用
有两种捕获类型:命名(又名“关联”)和编号(又名“位置”)。您在 <oneCSV>
周围的正则表达式中编写的括号引入了 numbered 捕获:
given 'ab'
{
my $m1 = m/ ( $<named-capture> = ( ab ) ) /; # extra parens added
say $m1[0]<named-capture>;
# 「ab」
}
/ ( ... ) /
中的括号声明单个顶级编号捕获。如果匹配,则对应的匹配对象存储在$m1[0]
中。 (如果您的正则表达式看起来像 / ... ( ... ) ... ( ... ) ... ( ... ) ... /
,那么与匹配第二对括号的内容对应的另一个匹配对象将存储在 $m1[1]
中,另一个存储在 $m1[2]
中,以此类推。)
然后$<named-capture> = ( ab )
的匹配结果存储在里面$m1[0]
。这就是 say $m1[0]<named-capture>
起作用的原因。
到目前为止一切顺利。但这只是故事的一半...
为什么您的代码中的 $m1[0]<oneCSV>
也不起作用
虽然上面代码中的 $m1[0]<named-capture>
有效,但您 仍然 无法在原始代码中的 $m1[0]<oneCSV>
中获得匹配对象。这是因为您还要求第 0 次捕获的 多个匹配项 因为您使用了 *
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]
等)。)
总结
夺巢;
通过
*
或+
量化的捕获对应于 两个 嵌套级别,而不仅仅是一个。在您的原始代码中,您必须编写
say $m1[0][0]<oneCSV>;
才能找到您要查找的匹配对象。
[1] 安装相关模块并写入 use Text::CSV;
(对于纯 Perl 6 实现)或 use Text::CSV:from<Perl5>;
(对于 Perl 5 plus XS 实现) 在代码的开头。 (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;
。 (talk slides, video, modules.)