一般に $&, $', $` を使うと処理速度が低下する。また,練習問題B2のように,ファイルを単位として処理する場合,処理速度が低下するだけでなく,メモリ不足などにより処理ができなくなることがある。
以下のようにすれば, $&, $', $` を使わなくとも,kwic1.pl と同じ処理ができる。(pos は未習。m/ /g でマッチした文字列の次の位置を返す関数。) こちらの方が kwic1.pl よりも長い文字列を単位として処理することができ,かつ処理速度も速い。
kwic1a.pl
--------------------------------------------------
#検索文字列の指定
$string = '\bjust\b';
#前後の文脈の長さの指定
$llen = 25;
$rlen = 25;
#ファイル単位で読み込む
$/ = undef;
while (<>) {
#左の文脈が指定の長さより短くなることがないよう処理
$_ = (' ' x $llen) . $_;
#空行は " <p> " で置き換え
s/ *\n\n+ */ <p> /g;
s/ *\n */ /g;
#$& の代りに $1 を使用するために,$string を ( ) で囲む
while(/($string)/ig){
$count++;
#$& の代りに $1 を使用
$key = $1;
#マッチした位置の次の位置を取得
$pos = pos $_;
#substr ($`, -$llen) の代り
$pre = substr ($_, ($pos - (length $key) - $llen), $llen);
#substr ($', 0, $rlen) の代り
$post = substr ($_, $pos, $rlen);
$file = $ARGV;
$file =~ s#.*/([^/]+)$#$1#;
printf "%5d | %s | %${llen}s|%s|%-${rlen}.${rlen}s\n",
$count, $file, $pre, $key, $post;
}
}
exit;
--------------------------------------------------
処理そのものができなくなる場合は別として,少し処理速度が低下する程度なら,処理速度は気にせず,自分にとってわかりやすい書き方をする方が現実的である。