はてなブックマークのコメント欄のようなものをParseするモジュール
はてなブックマークのコメント欄のようなものをParseするモジュールを組んでみた。
本家の完璧なエミュレートではないです。
package Text::HatenaBookmarkLike::Comment::Parser;
use strict;
use warnings;
sub new{
bless {},shift;
}
sub parse{
my $self = shift;
my $string = shift;
my @tags;
while(length $string && $string =~ m!^\s*\[([^\]]+)\]!){
my $tag = $1;
$string =~ s!^\s*\[([^\]]+)\]!!;
next unless length $tag;
push(@tags,$tag);
}
return Text::HatenaBookmarkLike::Comment::Parser::Result->new({
tags=>\@tags,
comment=>$string
});
}
1;
package Text::HatenaBookmarkLike::Comment::Parser::Result;
use strict;
use warnings;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_ro_accessors(qw(tags comment));
sub tags{
my $self = shift;
return wantarray ? @{$self->{tags}||[]} : $self->{tags};
}
sub uniq_tags{
my $self = shift;
my %seen;
my @tags = grep {!$seen{$_}++} $self->tags;
return wantarray ? @tags : \@tags;
}
1;
使い方は、
my $ret = Text::HatenaBookmarkLike::Comment::Parser->parse("[foo][bar][baz][foo]適当です");
print join(",",$ret->tags),"\n";
print join(",",$ret->uniq_tags),"\n";#ユニークなTagだけ
print $ret->comment,"\n";
今分かっている本家と違うところは、
- Tagの数、コメントの文字数に制限がない
- ? / % [ ] などの記号が使える
あたりが違う。
Tagの抜き出しの方法として、正規表現の\Gを使うことも考えられるのですが、上の方法の方が速かったです。
↓確認ベンチマークスクリプト
use strict;
use Benchmark;
my $str="[foo][bar][baz][foo]適当です";
Benchmark::timethese(300000, {
'USE_G' =>\&use_g,
'USE_S' => \&use_s,
});
sub use_g{
my $str = shift;
my @tags;
while($str =~ /\G\s*\[([^\]]+)\]/gc){
my $tag = $1;
push(@tags,$tag) if length $tag;
}
$str =~ /\G\s*(.*)/g;
my $comment = $1;
}
sub use_s{
my $str = shift;
my @tags;
while($str =~ /^\s*\[([^\]]+)\]/){
my $tag = $1;
push(@tags,$tag) if length $tag;
$str =~ s/^\s*\[([^\]]+)\]//i;
}
my $comment = $str;
}
実行結果
$ perl tag_seprate.pl
Benchmark: timing 300000 iterations of USE_G, USE_S...
USE_G: 2 wallclock secs ( 1.49 usr + 0.01 sys = 1.50 CPU) @ 200000.00/s (n=300000)
USE_S: 1 wallclock secs ( 0.47 usr + 0.00 sys = 0.47 CPU) @ 638297.87/s (n=300000)