补充克里斯托夫回答的详细讨论
我正在尝试解析一个 csv 文件
也许您专注于学习 Perl 6 解析并且正在编写一些一次性代码。但是,如果您想要开箱即用的工业级 CSV 解析,请注意 Text::CSV 模块[1]。
我正在尝试访问一个命名的正则表达式
如果您正在学习 Perl 6 解析,请注意 jnthn 的语法跟踪器和调试器[2]。
在 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> 编写的括号引入了编号捕获:
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> 中找不到匹配对象。这是因为您还请求了第零次捕获的多个匹配,因为您使用了 * 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] 等)。)
总结
[1] 安装相关模块并在代码开头写上use Text::CSV;(用于纯Perl 6 实现)或use Text::CSV:from<Perl5>;(用于Perl 5 plus XS 实现)。 (talk slides(单击最上面的单词,例如“csv”,以浏览幻灯片),video,Perl 6 module,Perl 5 XS module。)
[2] 安装相关模块并在代码开头写use Grammar::Tracer;或use Grammar::Debugger;`。 (talk slides, video, modules.)