Regex 如何访问匹配中的捕获?

Regex 如何访问匹配中的捕获?,regex,match,raku,named,Regex,Match,Raku,Named,我试图解析一个csv文件,并试图访问Perl6中proto regex中的名称regex。结果是零。正确的方法是什么 grammar rsCSV { regex TOP { ( \s* <oneCSV> \s* \, \s* )* } proto regex oneCSV {*} regex oneCSV:sym<noQuote> { <-[\"]>*? } regex oneCSV:sym<qu

我试图解析一个csv文件,并试图访问Perl6中proto regex中的名称regex。结果是零。正确的方法是什么

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];
语法rsCSV{ 正则表达式TOP{(\s*\s*\,\s*)*} proto regex oneCSV{*} regex oneCSV:sym{匹配的
位于捕获组的范围内,您可以通过
$m1[0]
获得该组

由于使用
*
对组进行量化,结果将再次成为一个列表,即您需要另一个索引操作来获取匹配对象,例如第一个对象的
$m1[0][0]

然后可以通过名称访问命名的捕获,例如
$m1[0][0]
。这将包含protoregex的相应分支的匹配结果

如果您想要完整的匹配列表而不是特定的匹配列表,您可以使用
>
map
,例如
$m1[0]>.

详细讨论补充Christoph的答案 我正在尝试解析csv文件

也许您正专注于学习Perl 6解析,并正在编写一些一次性代码。但是,如果您希望工业级CSV解析开箱即用,请注意Text::CSV模块[1]

我正在尝试访问一个命名的正则表达式

如果您正在学习Perl 6解析,请注意jnthn的语法跟踪器和调试器[2]

在Perl6的proto regex中

你的问题与它是一个原始正则表达式无关

相反,问题在于,虽然与命名捕获相对应的匹配对象存储在您存储在
$m1
中的整体匹配对象中,但它并没有准确地存储在您要查找它的位置

与捕获相对应的匹配对象出现在哪里? 要了解发生了什么,我将首先模拟您试图执行的操作。我将使用一个只声明一个捕获的正则表达式,一个与字符串
ab
匹配的“命名”(也称为“关联”)捕获

given 'ab'
{
    my $m1 = m/ $<named-capture> = ( ab ) /;

    say $m1<named-capture>;
    # 「ab」
}
/(…)/
中的参数声明一个顶级编号的捕获。如果匹配,则相应的匹配对象存储在
$m1[0]
中(如果您的正则表达式看起来像
/…(…)(…)…/
然后与第二对括号匹配的另一个匹配对象将存储在
$m1[1]
中,第三对括号对应的另一个匹配对象将存储在
$m1[2]
中,依此类推。)

$=(ab)
的匹配结果随后存储在
$m1[0]
中。这就是为什么
说$m1[0]
起作用的原因

到目前为止还不错,但这只是故事的一半

为什么代码中的
$m1[0]
也不起作用 当上述代码中的
$m1[0]
起作用时,您仍然无法在原始代码中的
$m1[0]
中获得匹配对象。这是因为您使用了
*
,因此还要求对第零次捕获进行多个匹配:

给定“ab”
{
my$m1=m/($=(ab))*/;#*是一个量词
表示为1美元[0][0];
#ab
}
由于
*
量词要求多个匹配,Perl 6将一个匹配对象列表写入
$m1[0]
(在这种情况下,只有一个这样的匹配,因此最终的列表长度为1,即只有
$m1[0][0]
(而不是
$m1[0][1]
$m1[0][2]

总结
  • 捕捉鸟巢

  • 通过
    *
    +
    量化的捕获对应于两个嵌套级别,而不仅仅是一个

  • 在原始代码中,必须编写
    比如$m1[0][0];
    才能找到要查找的匹配对象


[1] 安装相关模块,并在代码开头编写
使用Text::CSV;
(对于纯Perl 6实现)或
使用Text::CSV:from;
(对于Perl 5 plus XS实现)。((单击顶部的单词,例如“CSV”,浏览幻灯片),,)


[2] 安装相关模块并在代码开头编写
use Grammar::Tracer;
use Grammar::Debugger;
。(,)

非常感谢,raiph!!!在您详细解释之后,我现在看到了我的问题。非常感谢您抽出时间!!!@lisprogtor不客气。如果您能告诉我具体是哪一位的话是/是对您最有帮助的,这对我特别有帮助。:)谢谢raiph。这是您对命名/编号捕获和匹配对象树之间的关联的解释,以及perl6使用*构造列表而不是单个对象的事实。再次感谢!感谢Christoph。您的帮助加深了我对Perl 6的理解答案!
given 'ab'
{
    my $m1 = m/ ( $<named-capture> = ( ab ) ) /; # extra parens added

    say $m1[0]<named-capture>;
    # 「ab」
}
given 'ab'
{
    my $m1 = m/ ( $<named-capture> = ( ab ) )* /; # * is a quantifier

    say $m1[0][0]<named-capture>;
    # 「ab」
}