我正在尝试解析一个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”,以浏览幻灯片),video,Perl 6 module和Perl 5 XS module。)[2]安装相关模块,并在代码的开头写入
use Grammar::Tracer;
或use Grammar::Debugger;
。 (talk slides,video,modules。)