Kimura Fuyuki
fuyuk****@hadal*****
2002年 12月 8日 (日) 17:27:08 JST
文字集合と正規表現のかかわりあいについての考察です。まあ経過報告のよう なものなので気楽に読んでください。 * 日本語の文字列をいじる場合、文字種(全角/半角、ひらがな/カタカナ等) を 判別したり切り分けたりする処理がよく必要になります。Scheme にはせっか く文字集合(SRFI-14)の概念があるのですから、これを使って文字種を表現し たいと思うのが自然でしょう。 まじめにやるなら Unicode Character Database の内容を定義することから始 めるのでしょうが、ここでは簡単に (define *hiragana* #[ぁ-ん]) というのが1個だけあるものとします。 しかし、文字集合をそのまま使うような処理は実際にはまれで、むしろ正規表 現のなかに組み込んで使うことのほうがはるかに多いのではないかと思います。 たとえば、ある文字列がひらがなのみからなるかどうかを判別する関数 hiragana? はこんなふうに書けます。 (use gauche.sequence) (define (char-set->regexp cs) (string->regexp (subseq (x->string cs) 1))) (define (hiragana? str) ((string->regexp (string-append "^" (regexp->string (char-set->regexp *hiragana*)) "+$")) str)) この hiragana? の中身があまりにまぬけなんじゃないか? というのが私のか かえている問題です。つまり、「文字集合と正規表現のあいだのいったりきた りをうまくやるにはどうしたらいいか」ということです(たぶん本質的には grep 的な正規表現の表記が Lisp となじまないという問題)。 上の例はわざわざ char-set->regexp なんてのを持ち込んでいるのが悪いんで あって、char-set->string を使えばずっと簡単に書けるんじゃないか? とい う意見もあると思いますが、これは場合によってはものすごく長い文字列が返っ てくるのであまり使いたくありません。 で、どうしたらいいか考えているわけです。 <案1> 正規表現中に # リテラルの記述を許す。 つまり、"[a-z]" と書くかわりに "#[a-z]" でもよしとするということです。 いろいろ問題のありそうなアイディアですが、もしこれが許されるなら、 hiragana? は次のように書けます。 (define (hiragana? str) ((string->regexp #`"^,|*hiragana*|+$") str)) <案2> SRE を導入する。 SRE についてはここ。(Emacs には sregex という似たようなのがあります) http://www.scsh.net/docu/html/man-Z-H-7.html#%_chap_6 で、SCSH 相当の関数が用意されているものとすると、次のように書けます。 (define (hiragana? str) ((sre->regexp `(: bos (+ ,(char-set->sre *hiragana*)) eos)) str)) * このへんは SCSH が一番充実しているみたいなので、SCSH での実装をもうちょっ と調べてみようと思います。(でもやっぱりものの考え方が ASCII 圏のような 気が) あと、正規表現を記述するための XML みたいなのがどこかにあったら教えて ください。SRE があるのだから無いわけないと思うのですが、どうもみつかり ません。 -- 木村 冬樹