2009/04/09(木)UOA のベンダーエージェント機能のクリップボードデータ

UOA のベンダーエージェント情報をパース?トークナイズ?するコードだけ試しに書いてみた。
プログラムっていうよりただの正規表現で、ぶっちゃけ俺は何もしてない。
あくまでサンプルとして書いたので $a 使いすぎとかそういうところは無視。
#! /usr/bin/perl
use strict;
use utf8;

while (<>) {
  chomp;
  my $str = $_;
  utf8::decode($str);
  $str =~ /(Bulk Order Deed Blessed) (重量: \d) (小口|大口) (\w+(?: ingot(?:s)?| leather)?) (高品質|標準) (個数: \d+)/igc;
  my $a = $1;
  my $b = $2;
  my $c = $3;
  my $d = $4;
  my $e = $5;
  my $f = $6;
  utf8::encode($a);
  utf8::encode($b);
  utf8::encode($c);
  utf8::encode($d);
  utf8::encode($e);
  utf8::encode($f);
  print "\$1: [$a] \$2: [$b] \$3: [$c] \$4: [$d] \$5: [$e] \$6: [$f]";
  while ($str =~ /\G \w((?:\w|\s)+: \d+)/gc) {
    my $a = $1;
    utf8::encode($a);
    print " [$a]";
  }
  print "\n";
}

例えば布大口の巫女のデータをこのスクリプトに食わせると

$1: [Bulk Order Deed Blessed] $2: [重量: 1] $3: [大口] $4: [cloth] $5: [標準] $6: [個数: 20] [ バンダナ: 20] [ shirt: 20] [ skirt: 20] [ thigh boots: 0]

こんな風に分割して返してくれる。


UOAがクリップボードにコピーしてくれるデータって機械的に処理するのにやさしい形じゃないなぁ。
split() 一発で終わるような形でくれればいいのに。
それを簡単にパースしてくれる Perl ってすげー。

以下、俺メモ。
Perl で UTF-8 環境での正規表現について。
Google 先生に聞くと、Perl 5.8.1 以降の情報を扱っているはずなのに「文字の内部コードの数値でもってマッチさせる」みたいな情報ばっか出てきて脳みそ沸くので、後で忘れた時のためにメモっておく。

こんな辺鄙なサイトを参考にする人がいるかはわからないが、実際に使うときは perldoc utf8, perldoc perlre を読んでから。このサイトだけ見て済ますのはよくない。
  • Perl にとって utf8 フラグの立っていない文字による文字列はバイト列であり文字列ではない
    • EUC とか ASCII なら文字列とバイト列問で特に区別しなくても問題ないらしい。Shift-JIS はシラネ。
    • なので UTF-8 一文字が \w にマッチするか、というとマルチバイト文字はマッチしない
    • マルチバイトな文字に対して正規表現マッチを行うと、マルチバイト文字の上位ビット、下位ビットにヒットする正規表現があると意図しないマッチが行われる。その後はアンカーの位置がプログラマの意図と1バイトずれる。
      • これがいわゆる「日本語正規表現がうまくいかない」状態。
  • utf8 フラグが立っている場合、Perl はその文字列を UTF-8 文字列として見做す。
    • 文字単位で見てくれるので、文字列の上位ビット、下位ビット部分に対してプログラマが意図しないマッチが行われることはない。\w は正しく UTF-8 の一文字とマッチする。
    • utf8 フラグの立った文字列を print() で出力すると警告が出る。文字化け(?)することもある。この場合 utf8::encode() で utf8 フラグを取り除く必要がある。
    • 標準入力から入ってきた文字列には utf8 フラグが立っていないので、正規表現マッチ等文字列として扱いたい場合は utf8::decode() して utf8 フラグを立ててやる。
      • バイナリを扱うケースもあるから標準入力に手が加わらないのは当然。
  • しがらみとかで UTF-8 が使えないっていうときは Encode::decode(), Encode::encode() とか?
    • くだらないしがらみだ