end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転しました

perlのUnicode Block正規表現とEncode::CJKConstantsによる文字クラス判定

unicodeには、ひらがなやカタカナ等の文字グループがblockとして定義されており、perl ver.5.8以降では、このblock名称による正規表現が使用できるそうです。

http://blog.livedoor.jp/sasata299/archives/51194035.html
http://module.jp/blog/regex_unicode_prop.html

unicodeにおけるblock名称一覧

unicodeで定義されているblockは、次のurlに記載されています。

http://web.hc.keio.ac.jp/~fujimura/lang/unicode.html
http://www.unicode.org/charts/



よく使うblockは数種類に限定できますが、半角カナや機種依存にはちょっと

日本語を扱う上で使用するunicode blockは、次のものが主体になると思いますが、半角カナや機種依存文字を特定するblock名は定義されていないようです。

block 説明
BasicLatin 半角英数字と半角記号
Hiragana ひらがな
Katakana カタカナ
CJKUnifiedIdeographs 漢字
CJKSymbolsAndPunctuation 全角記号
HalfwidthAndFullwidthForms 半角カナ等 ※全角0-9や全角a-zも含む

perlで使用できるunicode blockはperlunicode.podを参照ください

perlでは、ver.5.8からunicode blockを使用できるようですが、perlにおけるるunicode blockはperlunicode.podに記載されています。

http://perldoc.jp/docs/perl/5.10.0/perlunicode.pod

\p{In〜}によるblock正規表現。半角カナ判定はEncode::CJKConstantsで

perlunicode blockを用いた正規表現は「\p{In〜}」の形式で指定します。
※「〜」の部分には、block名を指定して下さい。
また、Encode::CJKConstantsにある %REを利用すれば、半角カナの特定も可能です。

Encode::CJKConstantsの抜粋

our %RE = (
    ASCII     => '[\x00-\x7f]',
    BIN       => '[\x00-\x06\x7f\xff]',
    EUC_0212  => '\x8f[\xa1-\xfe][\xa1-\xfe]',
    EUC_C     => '[\xa1-\xfe][\xa1-\xfe]',
    EUC_KANA  => '\x8e[\xa1-\xdf]',
    JIS_0208  => "$_0208{1978}|$_0208{1983}|$_0208{1990}",
    JIS_0212  => "\e" . '\$\(D',
    ISO_ASC   => "\e" . '\([BJ]',
    JIS_KANA  => "\e" . '\(I',
    '2022_KR' => "\e" . '\$\)C',
    SJIS_C    => '[\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc]',
    SJIS_KANA => '[\xa1-\xdf]',
    UTF8      => '[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf]'
);

次のscriptは日本語で使用しそうなblock正規表現と、$Encode::CJKConstants::RE{SJIS_KANA}で文字クラスを判定したもので、半角カナも含めて判定できていることが分かります。

#!/usr/local/bin/perl
use strict;
use warnings;
use encoding qw/cp932/;
use Encode;
use Encode::CJKConstants;

my $BLOCKS = {'BasicLatin'=>			'半角英数字と半角記号',
	      'Hiragana'=>			'ひらがな',
	      'Katakana'=>			'カタカナ',
	      'CJKUnifiedIdeographs'=>		'漢字',
	      'CJKSymbolsAndPunctuation'=>	'全角記号',
	      'HalfwidthAndFullwidthForms'=>	'半角カナ等'};
my @STRS = ("亜","あ","ア","ア","A","A","a","a","1","1","①","〇","㎡","㈱");

sub main {
    print ' 'x40;
    for my $str (@STRS){
	print sprintf("%-3s",encode("cp932",$str));
    }
    print "\n";

    for my $block (sort keys %$BLOCKS ){
	print sprintf("%-40s",encode("cp932","$block($BLOCKS->{$block})"));
	for my $str (@STRS){
	    #unicode blockによる文字クラス判定
	    my $match = ($str =~ /\p{In$block}/) ? 'o':'x';
	    print sprintf("%-3s",$match);
	}
	print "\n";
    }

    print sprintf("%-40s",encode("cp932","SJIS_KANA(半角カナ)"));
    for my $str (@STRS){
	#Encode::CJKConstantsによる半角カナ判定
	my $match = ($str =~ /$Encode::CJKConstants::RE{SJIS_KANA}/o) ? 'o':'x';
	print sprintf("%-3s",$match);
    }
    print "\n";
}

main();
[endo@colinux tmp]$ ./foo.pl 
                                        亜 あ ア ア  A A  a a  1 1  ① 〇 ㎡ ㈱ 
BasicLatin(半角英数字と半角記号)        x  x  x  x  x  o  x  o  x  o  x  x  x  x  
CJKSymbolsAndPunctuation(全角記号)      x  x  x  x  x  x  x  x  x  x  x  o  x  x  
CJKUnifiedIdeographs(漢字)              o  x  x  x  x  x  x  x  x  x  x  x  x  x  
HalfwidthAndFullwidthForms(半角カナ等)  x  x  x  o  o  x  o  x  o  x  x  x  x  x  
Hiragana(ひらがな)                      x  o  x  x  x  x  x  x  x  x  x  x  x  x  
Katakana(カタカナ)                      x  x  o  x  x  x  x  x  x  x  x  x  x  x  
SJIS_KANA(半角カナ)                     x  x  x  o  x  x  x  x  x  x  x  x  x  x  
[endo@colinux tmp]$ 

機種依存文字は特定できていませんが、それに関しては別の機会に