シリーズの第3回。
前回は、われわれ日本人が使いがちな文字種の分別はどうすればいいのかについてまとめてみた。

イジハピ! : 【第578回】UnicodeプロパティとPerl正規表現(その2:\d、\w、\sの範囲と/a修飾子(超便利!))

結果はこんな感じだった。

 ・全角ひらがな [\p{Hiragana}・ー゠]か[ぁ-ん・ー゠]  // カッコや丸で囲まれたひらがなは考慮していません
 ・全角カタカナ [\p{InKatakana}・ー゠]か[ァ-ン・ー゠] // カッコや丸で囲まれたカタカナは考慮していません
 ・漢字     \p{Han}か[\{Han}\x{3220}-\x{3244}\x{3280}-\x{32B0}] // 後ろの方はカッコや丸で囲まれた漢字を考慮しています
 ・半角カタカナ [ヲ-゚]か[。-゚]
 ・半角英数字  \wただし修飾子/aを使う(アンダースコアが入ることに注意)
 ・半角英字   \p{PosixAlpha}か[a-zA-Z]
 ・半角数字   \dただし修飾子/aを使う(アンダースコアが入らないことに注意)
 ・半角空白文字 \sただし修飾子/aを使う

でもなんだか、覚えることが多くて結局バッドノウハウという気がする。
特に上半分の方、もう少しスッキリ書けないだろうか。

自作のUnicodeプロパティ

Unicodeプロパティは次のようにサブルーチンを使って作ることが出来る。
perlunicode - Perl における Unicode サポート - perldoc.jp(ユーザ定義文字属性)
#! /usr/local/bin/perl
#
# regTestJ.pl -- Unicodeプロパティを使った正規表現のテスト(Mac/Unix用)
# (※UTF-8で保存し、改行コードはCRLFにする)

use 5.010;
use strict;
use warnings;
use utf8;
binmode STDOUT, ":encoding(UTF-8)";

my @str = ();

while() {
 chomp;
 say;
 say "\tひらがな:@str" if @str = /\p{InHrkn}+/g;
}

sub InHrkn {
 return < 3014 3093 # ぁ-ん
3094 3096 # う点、小書きのかとけ
3099 309C # 濁点、半濁点
309D 309E # 繰り返し記号
30A0 # ダブルハイフン
30FB # 中黒
30FC # 長音記号
309F #「より」の合字
1B001 # や行え段の古字
1F200 #「ほか」の組み文字
END
}
__DATA__
ふぁんたじー幻想
豪華ゔぁらえてぃ
現実ゟ夢
実行してみる。
[perl]$ regTestJ.pl
ふぁんたじー幻想
  ひらがな:ふぁんたじー
豪華ゔぁらえてぃ
  ひらがな:ゔぁらえてぃ
現実ゟ夢
  ひらがな:ゟ
[perl]$
できてるっぽい。

InHrknはユーザー定義属性の名前である。
これ、割りと最近のPerlでIsまたはInで始まることが必須になった。
文字コード【超】研究の記述は古くなっているので(執筆当時はIs/Inを書かなくても動作した)注意してください。スミマセン。

ユーザー定義属性の中に既存の(組み込みまたは自作の)文字属性を入れることができるので、InHrknはもっと簡略化できる。
sub InHrkn {
 return < +utf8::Hiragana
3099 309C # 濁点、半濁点
30A0 # ダブルハイフン
30FB # 中黒
30FC # 長音記号
END
}
このように+で\p{Hiragana}プロパティを追加しているが、他に-で削除したり、!で否定したり、&で共通部分を括りだしたりできる。
融通無碍である。

クォート正規表現qr//

他の方法としては、クォート正規表現 qr/パターン/ という書き方があって、正規表現をスカラー変数に閉じ込めることが出来る。

以下は「$ぁ」という変数にひらがな1文字の正規表現を入れている。
#! /usr/local/bin/perl
#
# regTestJ2.pl -- 正規表現リファレンス qr を使った正規表現のテスト(Mac/Unix用)
# (※UTF-8で保存し、改行コードはCRLFにする)

use 5.010;
use strict;
use warnings;
use utf8;
binmode STDOUT, ":encoding(UTF-8)";

my $ぁ = qr![\p{Hiragana}\N{U+3099}-\N{U+309C}\N{U+30A0}\N{U+30FC}]!;

my @str = ();

while() {
 chomp;
 say;
 say "\tひらがな:@str " if @str = m|$ぁ+|g;
}

__DATA__
黄金の日々
ふぁんたじー幻想
豪華ゔぁらえてぃ
現実ゟ夢
これ結構スッキリ書けていると思うのだがどうだろうか。
use utf8状態では非英数字の変数が使えるのだが、めったに使わない。
しかし、正規表現リファレンスだけは日本語を使うという自分ルールを決めておけば、上のように1字で書けるので非常に見やすいと思う。

ということで、
my $ぁ = qr![\p{Hiragana}・ー゠]!; # ひらがな
my $あ = qr![^\p{Hiragana}・ー゠]!; # ひらがな以外
my $ァ = qr![\p{InKatakana}・ー゠]!; # 全角カタカナ
my $ア = qr![^\p{InKatakana}・ー゠]!; # 全角カタカナ以外
my $漢 = qr![\p{Han}]!; #漢字
my $非 = qr![\P{Han}]!; #漢字以外
my $ァ = qr![。-゚]!; # 半角カナ
my $ア = qr![^。-゚]!; # 半角カナ以外
my $w = qr![a-zA-Z0-9_]!; # 半角英数字
my $W = qr![^a-zA-Z0-9_]!; # 半角英数字以外
my $e = qr![a-zA-Z]!; # 半角英字
my $E = qr![^a-zA-Z]!; # 半角英字以外
my $d = qr![0-9]!; # 半角数字
my $D = qr![^0-9]!; # 半角数字以外
my $s = qr![ \t\n\r\f]!; # 半角スペース
my $S = qr![^ \t\n\r\f]!; # 半角スペース以外
などと考えられる。

$w、$W、$d、$D、$s、$Sは既存の文字クラスショートカット\w、\W、\d、\D、\s、\Sに合わせてみた。
そうするとひらがなは小書きのかなを使って「$ぁ」で、ひらがな以外は「$あ」、カタカナは「$ァ」でカタカナ以外は「$ア」としてみたがどうだろうか。
漢字は$漢、非漢字は非というのはいかにも苦しいな。

半角英字はアルファベットだから$aにしようかと思ったのだが、$aという変数は$bと共にsort関数の並び順カスタマイズに使うので、うまくない。
イングリッシュの$eにしてみたが、$eだと自然対数の底に勘違いされるだろうか。
ラテンの$lの方がいいかもしれない。

Regulares