#!/usr/bin/perl -w # dump_storableを読み込んで、テキストからキーワードを探し出す。 # Storableモジュールが必要(CPANにあるがPerl5.8以降は標準モジュール) use strict; use Storable; main(); sub main{ my $hash = ${ retrieve('dump_storable') }; my $text = $ARGV[0]; my $result = find_keyword_storable($hash,$text); print $_,"\n" for(@$result); } # # 処理速度を出すため、あえて同じ操作をするコードをまとめていない # sub find_keyword_storable{ my $hash = shift; my $text = lc( shift ); my $strlen = length $text; my $index = 0; # 現在調べている文字の先頭の位置(探査位置) my %found; while($strlen > $index){ my $char = substr($text,$index,1); my $code = ord($char); # http://d.hatena.ne.jp/uno/20040222#p3 を参考にしました my $clen = ($code < 0x80) ? 1 : ($code == 0x8f ? 3 : 2); $char .= substr($text, $index+1, $clen - 1) if($clen > 1); my $data = $hash; my $i = $index + length($char); # 単語にマッチするか調べている位置 my $str; # 途中までマッチした文字列 my $reserve; # 最終的にマッチした単語を格納 while( defined ($data->{$char}) ){ if(ref($data->{$char}) eq 'HASH'){ $data = $data->{$char}; # ハッシュを辿る $str .= $char; } elsif(ref($data->{$char}) eq 'ARRAY'){ # ひとまずマッチしたので my $tempdata = $data->{$char}->[0]; # 次の一文字を調べる my $tempc = substr($text,$i,1); $code = ord($tempc); $clen = ($code < 0x80) ? 1 : ($code == 0x8f ? 3 : 2); $tempc .= substr($text, $i+1, $clen - 1) if($clen > 1); if(!defined ($tempdata->{$tempc})){ # もうハッシュを辿れないので $reserve = $str . $char; # この単語で確定 last; } else{ $reserve = $data->{$char}->[1]; # まだマッチするようなので $data = $data->{$char}->[0]; # ひとまずマッチの候補に $str .= $char; } } else{ # リファレンスではないので $str .= $char; # この単語がマッチ $reserve = $str; last; } $char = substr($text,$i,1); $code = ord($char); $clen = ($code < 0x80) ? 1 : ($code == 0x8f ? 3 : 2); $char .= substr($text, $i+1, $clen - 1) if($clen > 1); $i += length($char); # 一文字(1-3byte)移動 } if(defined $reserve){ # マッチした単語を発見したので $found{$reserve} = 1; # 単語分だけ探査位置を移動 $index += length($reserve); } elsif(!defined $str){ # 何も発見できず。一文字移動 $index = $i; } else{ # 途中まで進んだがマッチせず $index += length($str); # その分だけ探査位置を移動 } } my @found = map { $_->[0] } sort{ $b->[1] <=> $a->[1] } map { [$_,length($_)] } keys %found; return \@found; }