なぜ正規表現を使用しているのですか? リテラル テキスト {{ または }} の位置を探しています。Perl には、まさにそれを行うビルトインがあります: index。
ウィキペディアのエントリを解析しようとしているので、ネストされたテンプレート ディレクティブを処理する必要があります。これは、たとえば、見つけた 2 番目の閉じたカーリーのセットが、2 番目の開いたカーリーのセットと必ずしも一致しないことを意味します。Perlエントリからのこのビットでは、最初の閉じのカーリーが 2 番目のオープニングのカーリーと一緒になっています。
{{Infobox プログラミング言語
| | 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 (リビジョン 5 バージョン 8 サブバージョン 8) 構成の概要:
プラットホーム:
osname=ダーウィン、osvers=8.8.2、archname=ダーウィン-2レベル
uname='darwin macbookpro.local 8.8.2 ダーウィン カーネル バージョン 8.8.2: 2006 年 9 月 28 日 20:43:26 pdt; root:xnu-792.14.14.obj~1release_i386 i386 i386 '
config_args='-des'
ヒント = 推奨、useposix = true、d_sigaction = 定義
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=usesocks=undef を定義
use64bitint=未定義 use64bitall=未定義 uselongdouble=未定義
usemymalloc=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. ビルド 5363)', gccosandvers=''
intsize=4、longsize=4、ptrsize=4、doublesize=8、byteorder=1234
d_longlong=定義、longlongsize=8、d_longdbl=定義、longdblsize=16
ivtype='long'、ivsize=4、nvtype='double'、nvsize=8、Off_t='off_t'、lseeksize=8
alignbytes=8、プロトタイプ=define
リンカーとライブラリ:
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
libs=-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=バンドル、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