你为什么使用正则表达式?您正在寻找文字文本 {{ 或 }} 的位置。Perl 有一个内置函数可以做到这一点:index。
由于您正在尝试解析 Wikipedia 条目,因此您需要处理嵌套的模板指令。这意味着,例如,您找到的第二组闭合卷曲不一定与第二组开放卷曲一起使用。在Perl条目的这一点中,第一个结束卷曲与第二个开始卷曲一起出现:
{{信息框编程语言
| latest_release_version = 5.10.0
| latest_release_date = {{发布日期|mf=yes|2007|12|18}}
| 图灵完备 = 是
}}
Perl 5.10 正则表达式可以为您处理这个问题,因为它们可以递归地匹配平衡文本,并且还有 Perl 模块可以做到这一点。不过,这将是一些工作。在你说出你想要完成的事情之前,很难给你任何建议。肯定有一个 mediawiki 解析器可以做你想做的事情。
我打算编写我的index()
解决方案,但我没有。我不能让你的代码足够慢以至于它很重要。即使我完成了所有堆栈管理并打印了每个模板的内容,这两个解决方案对我来说几乎都是即时完成pos()
的。@-
我必须非常努力地让它运行得足够慢才能被测量,而且我在一些旧硬件上。您可能需要以其他方式调整您的应用程序。
你确定你正在测量的代码在你认为的那一点上变慢了吗?您是否使用Devel::NYTProf 对其进行了概要分析,以了解您的实际程序在做什么?
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark;
my $text = do { local $/; <DATA> }; # put the contents after __END__
my %subs = (
using_pos => sub {
my $page = shift;
my @stack;
my $found;
while( $$page =~ m/ ( \{\{ | }} ) /xg ) {
if( $1 eq '{{' ) { push @stack, pos($$page) - 2; }
else
{
my $start = pop @stack;
print STDERR "\tFound at $start: ", substr( $$page, $start, pos($$page) - $start ), "\n";
$found++;
};
}
print " Processed $found templates => ";
},
using_special => sub {
my $page = shift;
my @stack;
my $found;
while( $$page =~ m/ ( \{\{ | }} ) /xg ) {
if( $1 eq '{{' ) { push @stack, $-[0]; }
else
{
my $start = pop @stack;
print STDERR "\tFound at $start: ", substr( $$page, $start, $-[0] - $start ), "\n";
$found++;
};
}
print " Processed $found templates => ";
},
);
foreach my $key ( keys %subs )
{
printf "%15s => ", $key;
my $t = timeit( 1, sub{ $subs{$key}->( \$text ) } );
print timestr($t), "\n";
}
我的 17" MacBook Pro 上的 perl:
macbookpro_brian[349]$ perl -V
我的perl5(revision 5 version 8 subversion 8)配置总结:
平台:
osname=darwin,osvers=8.8.2,archname=darwin-2level
uname='darwin macbookpro.local 8.8.2 darwin kernel version 8.8.2: thu sep 28 20:43:26 pdt 2006; 根:xnu-792.14.14.obj~1release_i386 i386 i386 '
config_args='-des'
提示=推荐,useposix=true,d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define useocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
使用mymalloc=n,bincompat5005=undef
编译器:
cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -I/opt/local/包括',
优化='-O3',
cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -I/opt/local/包括'
ccversion='', gccversion='4.0.1 (Apple Computer, Inc. build 5363)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define,longlongsize=8,d_longdbl=define,longdblsize=16
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=8,原型=定义
链接器和库:
ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -L/usr/local/lib -L/opt/local/lib'
libpth=/usr/local/lib /opt/local/lib /usr/lib
库=-ldbm -ldl -lm -lc
perllibs=-ldl -lm -lc
libc=/usr/lib/libc.dylib,so=dylib,useshrplib=false,libperl=libperl.a
gnulibc_version=''
动态链接:
dlsrc=dl_dlopen.xs,dlext=bundle,d_dlsymun=undef,ccdlflags=''
cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib'
此二进制文件的特征(来自 libperl):
编译时选项:PERL_MALLOC_WRAP USE_LARGE_FILES USE_PERLIO
建于达尔文之下
编译于 2007 年 4 月 9 日 10:36:26
@INC:
/usr/local/lib/perl5/5.8.8/darwin-2level
/usr/local/lib/perl5/5.8.8
/usr/local/lib/perl5/site_perl/5.8.8/darwin-2level
/usr/local/lib/perl5/site_perl/5.8.8
/usr/local/lib/perl5/site_perl