补充克里斯托夫答案的详细讨论
我正在尝试解析 csv 文件
Perhaps you are focused on learning Raku 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].
我正在尝试访问命名的正则表达式
If you are learning Raku parsing, please take advantage of the awesome related (free) developer tools[2].
在 Raku 的原始正则表达式中
您的问题与原始正则表达式无关。
相反,问题是,虽然与您的命名捕获对应的匹配对象is存储在您存储的整体匹配对象中$m1
,它没有准确存储在您要查找的位置。
与捕获相对应的匹配对象出现在哪里?
为了了解发生了什么,我将首先模拟您尝试执行的操作。我将使用一个仅声明一次捕获的正则表达式,即与字符串匹配的“命名”(又名“关联”)捕获ab
.
given 'ab'
{
my $m1 = m/ $<named-capture> = ( ab ) /;
say $m1<named-capture>;
# 「ab」
}
与指定捕获相对应的匹配对象存储在您可能期望它出现的位置$m1
, at $m1<named-capture>
.
但你得到的是 Nil$m1<oneCSV>
。是什么赋予了?
为什么你的$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 )
然后被存储inside $m1[0]
。这就是为什么say $m1[0]<named-capture>
works.
到目前为止,一切都很好。但这只是故事的一半......
Why $m1[0]<oneCSV>
在你的代码中也不起作用
While $m1[0]<named-capture>
在上面的代码正在工作中,你会still没有得到匹配对象$m1[0]<oneCSV>
在你的原始代码中。这是因为您还要求多次匹配第零次捕获的,因为您使用了*
量词:
given 'ab'
{
my $m1 = m/ ( $<named-capture> = ( ab ) )* /; # * is a quantifier
say $m1[0][0]<named-capture>;
# 「ab」
}
因为*
量词要求多个匹配,Raku 写了一个list匹配对象的数量$m1[0]
。 (在这种情况下,只有一个这样的匹配,所以你最终会得到一个长度为 1 的列表,即$m1[0][0]
(并不是$m1[0][1]
, $m1[0][2]
, ETC。)。)
Summary
[1] Install relevant modules and write use Text::CSV;
(for a pure Raku implementation) or use Text::CSV:from<Perl5>;
(for a Perl plus XS implementation) at the start of your code. (talk slides (click on top word, eg. "csv", to advance through slides), video, Raku module, Perl XS module.)
[2] Install CommaIDE and have fun with its awesome grammar/regex development/debugging/analysis features. Or install the Grammar::Tracer;
and/or Grammar::Debugger
modules and write use Grammar::Tracer;
or use Grammar::Debugger;
at the start of your code (talk slides, video, modules.)