我正在尝试解析一个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];

最佳答案

详细讨论补充了克里斯托夫的答案

我正在尝试解析一个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>不起作用
捕获有两种类型:命名捕获(又名“关联”)和编号捕获(又名“Postional”)。您在正则表达式中写的包围<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]等)。)
摘要
  • 捕获嵌套;
  • *+量化的捕获对应于两个嵌套级别,而不仅仅是一个嵌套级别。
  • 在原始代码中,您必须编写say $m1[0][0]<oneCSV>;才能找到所需的匹配对象。

  • [1]安装相关模块,并在代码开始处编写use Text::CSV;(对于纯Perl 6实现)或use Text::CSV:from<Perl5>;(对于Perl 5 plus XS实现)。 (talk slides(单击顶部单词,例如“csv”,以浏览幻灯片),videoPerl 6 modulePerl 5 XS module。)
    [2]安装相关模块,并在代码的开头写入use Grammar::Tracer;use Grammar::Debugger;。 (talk slidesvideomodules。)

    10-05 20:16
    查看更多