基本上,我制作了一堆Perl代码,目前产生如下输出:
if: 12
for: 26
rof: 26
fi: 27
for: 25
rof: 25
fi: 27
...some more backtracking...
if: 9
fi: 9
for: 26
rof: 26
每一行都是由正则表达式中的代码生成的事件,格式为:title: position
。
(我没有询问正则表达式;它完美地描述了我编写的一个简单的CFG。不要提及它的任何内容,我只需要帮助存储然后检索它的数据。已打印。)
我希望sub mark
将此数据放入数据结构中。但我不确定最好的方法。我需要能够以三种方式检索数据(以每个方式为例):
for
的哪些事件?我也想避免重复的提案。如果fi: 27
作为第四和第八个事件发生,我想要一个条目,其顺序是4,8,
之类的数组。
请记住,我对Perl非常缺乏经验,我很欣赏代码示例(解释如何使用迭代进行存储和检索)。我知道似乎有三种类型的数据结构:$
,@
和%
。我没有比这更进一步,因为Perl的结构与Java(我最有经验)完全不同。
随时请我澄清任何事情。
我的代码很简单,除了正则表达式:
sub mark{
my ($title, $position)= @_;
print "\n";
print $title;
print $position;
}
$re = qr{
((?&line))
|(*F)(?:
(?'line' (?&if)|(?&for))
(?'if' if \((?&exp)*\)\{\s*(?{mark("if: ", pos)})(?&line)*(?{mark("fi: ", pos)})\s*\})
(?'for' for\((?&exp)*\)\{\s*(?{mark("for: ",pos)})(?&line)*(?{mark("rof: ",pos)})\s*\})
(?'eq' [=])
(?'exp' (?&abc)(\s?(?&eq)\s?(?&num)+)?)
(?'num' [0-9])
(?'abc'[a-z])
(?'space' \s)
)}xm;
# I've been changing the following 'string' to test different stuff
# This is the run that produced the sample data
# 'oops;' doesn't follow the grammar rules, so it shows how the regex may backtrack
'if(true){
for(i = 5){
}
oops;
}' =~ /$re/
and print "\n\n$1\n\n";
答案 0 :(得分:2)
我创建了一个数组来保持顺序(@ordered),下面的代码存储了标题和位置。其他两个哈希值,%by_title和%by_position,只是使查找更快。它们只将索引存储到@ordered数组。
use feature qw{ say };
use constant {
TITLE => 0,
POSITION => 1,
};
my (%by_title, %by_position, @ordered);
my $order = 0;
sub mark{
my ($title, $position)= @_;
push @{ $by_title{$title} }, $order;
push @{ $by_position{$position} }, $order;
push @ordered, [ $title, $position ];
++$order;
}
# ...
say "Last: @{ $ordered[-1] }";
say 'Other at the same position:',
join ', ', map "@{ $ordered[$_] }",
@{ $by_position{ $ordered[-1][POSITION] } };
say 'Other with the same title: ',
join ', ', map "@{ $ordered[$_] }",
@{ $by_title{ $ordered[-1][TITLE] } };
答案 1 :(得分:0)
您需要的是存储标题的哈希值,以及存储位置的数组引用。这看起来像下面这样:
$VAR1 = {
'rof: ' => [
'26',
'25',
'24',
'23',
'26'
],
'for: ' => [
'26',
'25',
'24',
'23',
'26'
],
'fi: ' => [
'27',
'27',
'27',
'27',
'12',
'11',
'10',
'9'
],
'if: ' => [
'12',
'11',
'10',
'9'
]
};
我通过做出这些改变来制作它。
use strict;
use warnings;
use Data::Dumper;
my %foo;
sub mark{
my ($title, $position)= @_;
push @{ $foo{$title} }, $position;
}
# your regex and match here
print Dumper \%foo;
要访问这些内容,您可以使用keys
keyword进行迭代,并使用@{ $foo{$key} }
取消引用以访问数组。
您应该阅读perldata,perlref和perlreftut,您可能也对re
pragma's debug mode感兴趣。