Perlの正規表現は、対象の文字を検索するだけでなく、文字変換にも使えます。

この記事では正規表現を使った文字変換の方法を2種類ご紹介し、最後に、その一つを使ってひらがなをカタカナに変換するサンプルプログラムを作ります。サンプルプログラムは、集めた名簿データの振り仮名欄がひらがな、カタカナ混合の場合にこれを統一するという想定の機能です。

この記事では以下の事を説明します。

  1. Perlの置換関数2種類
    • s///
    • tr///
  2. 「ふりがな」を「フリガナ」に変換するサンプルプログラム

Perl の正規表現のおさらい


Perl の正規表現は、以下のように、探している文字が対象に含まれるかをチェックするための検索機能でした。

$str = '東京都';
if ($str =~ m/京都/){
	print '「京都」にマッチしました。';
}

この時使った m// という記号は、マッチするかを知りたいだけの時に使うものです。

置換用の Perl 関数 s///


正規表現にマッチした文字列を置換する時は、s/// という記号を使います。例えば以下のようにして、日本語にある「表記の揺れ」を修正できます。

$str = 'このコンピューターは複数のユーザが同時に利用できるように設計されています。';
$str =~ s/コンピューター/コンピュータ/g;
print "$str
";

書式は以下の通りです。

(変換対象) =~ s/正規表現/置換文字列/オプション;

正規表現のオプション


オプションは色々ありますが、このような置換をする場合に使うものは次の2つです。

g     複数個所でマッチしたらすべてを置換する。 
      (このオプションを付けないと、最初の1個だけ置換する。) 
i     大文字と小文字の区別をしない。 
      (正規表現部分のみに適用。置換文字列は指定した通りに置換される。) 

大文字小文字の区別ができるのは半角のアルファベットだけですが、例えば以下のように利用できます。

$str = 'iPHONE を持っていますか? iphone 用のサーバ管理ツールは既にいくつくも公開されています。';
$str =~ s/iphone/iPhone/gi;
print "$str
";

/i オプションを付けると、「iPHONE」も「iphone」も変換され「iPhone」に置き換えられます。

複雑な正規表現


正規表現部分は、m// の場合と同じように、「?」「*」「+」など記号を含む Perl の正規表現がすべて使えます。

$str = 'iフォン を持っていますか? アイホーン用のサーバ管理ツールは既にいくつくも公開されています。';
$str =~ s/(i|アイ)(phone|fone|ホー?ン|フォー?ン)/iPhone/gi;
print "$str
";

この指定で、「iphone」「Iフォン」「アイホン」「アイphone」「iフォーン」などの表記を全て「iPhone」に統一できます。

ここで使っている記号「|」 (垂直バーは) 「または」の意味で、「i」と「アイ」などの複数の可能性があるときに、この記号でつないでまとめて指定する事ができます。またこの選択肢の及ぶ範囲を丸カッコで括って表します。上では丸カッコを使って、「『i』または『アイ』」の部分と「『phone』または『fone』または『ホー?ン』または『フォー?ン』」に分けています。

正規表現プログラムのコツ


正規表現は、Perl プログラマの腕の見せ所でもあるので、時々凝った事をしてみたくなる事があります。

例えば、上に挙げた例の中の以下の部分は、

(phone|fone|ホー?ン|フォー?ン)

「phone」と「fone」は「ph」と「f」が違うだけ、「ホン」と「フォン」は「ホ」と「フォ」が違うだけです。このため、これらをまとめて以下のように書くこともできます。

(((ph|f)one)|((ホ|フォ)ー?ン))

プログラムをしていると、こういうところに懲りたくなる場合があります。もちろんそれは悪い事ではないのですが、このような正規表現は書くのも面倒、修正も面倒です。このため、あまり正規表現の効率にこだわらず、見やすさも考慮した上で、プログラムを作成する方が効率的です。上の例でしたら、以下のように単純に候補を全て列挙してもよいかも知れません。自分がやりやすい方でやって下さい。

(phone|fone|ホン|フォン|ホーン|フォーン)

一文字ずつ置換する tr///


さて、この記事では「ふりがな」を「フリガナ」のようにひらがな→カタカナ変換するプログラムを作りますが、s/// を使って「あ」を「ア」に、「い」を「イ」に変換できますね。

例えば以下のようにです。

$name = 'やまだ たろう';

$name =~ s/あ/ア/g;
$name =~ s/い/イ/g;
:
$name =~ s/や/ヤ/g;
:
$name =~ s/ん/ン/g;
print "$name
";

さてでも、50音および濁点付や小さい音まですべていちいち変換していくのは面倒です。このような場合、変換する対象が1文字 対 1文字 で対応しているならば、tr/// という関数が使えます。

例えば、

$name =~ s/あ/ア/g;
$name =~ s/い/イ/g;
$name =~ s/う/ウ/g;
$name =~ s/え/エ/g;
$name =~ s/お/オ/g;
は、tr/// を使うと以下のように書く事ができます。

$name =~ tr/あいうえお/アイウエオ/;

形式は以下の通りです。

(変換対象) =~ tr/変換する文字の一覧/変換する文字の一覧のそれぞれに対応する変換後の文字の一覧/;
例えば以下のように変換すると

$name = 'やまだ たろう';
$name =~ tr/あいうえお/アイウエオ/;
print "$name
";

結果は「やまだ たろウ」になります。「あいうえお」という文字列を探すわけではない事に注意して下さい。 (ですから、tr/// は厳密に言うと「正規表現」を使った関数ではないです。)

50音すべてを変換したい場合は、s/A/B/ の A、B それぞれに変換対象の文字を全て並べればよいのですが、小さい文字や濁点付などのものを全部並べてしまうと対応がきちんと一致しているかの確認がなかなか大変です。このため、以下のように少しずつ並べるのがお勧めです。

$name =~ tr/ぁあぃいぅうぇえぉおかがきぎくぐけげこご/ァアィイゥウェエォオカガキギクグケゲコゴ/;
:
$name =~ tr/ゎわゐゑをんゔゕゖ/ヮワヰヱヲンヴヵヶ/;

「ふりがな」を「フリガナ」に変換するプログラム


では、tr/// を使って、名簿CSV の「ふりがな」を「フリガナ」に変換するプログラムを作ってみましょう。前回のメールアドレスチェックプログラムの場合と同様、変換するためのサブルーチンは別のファイルに分けます。

ダウンロードはこちら:csvutil.pl
#CSV用ユーティリティー

use strict;
use warnings;
use utf8;

#ひらがなカタカナ変換
#引数:文字列
#戻り値:文字列

sub hira2kata{
	my $str = shift;

	#空文字列ならそのまま返す
	length $str or return $str;

	$str =~ tr/ぁあぃいぅうぇえぉおかがきぎくぐけげこご/ァアィイゥウェエォオカガキギクグケゲコゴ/;
	$str =~ tr/さざしじすずせぜそぞただちぢっつづてでとど/サザシジスズセゼソゾタダチヂッツヅテデトド/;
	$str =~ tr/なにぬねのはばぱひびぴふぶぷへべぺほぼぽ/ナニヌネノハバパヒビピフブプヘベペホボポ/;
	$str =~ tr/まみむめもゃやゅゆょよらりるれろ/マミムメモャヤュユョヨラリルレロ/;
	$str =~ tr/ゎわゐゑをんゔゕゖ/ヮワヰヱヲンヴヵヶ/;

	return $str;
}


1;

入力CSVファイル


入力のCSVは以下のように想定しました。例によってですが、変換対象の列がどこか (今回の場合は、読み仮名が入っている3番目) を把握しておくことが必要です。
ひらがなカタカナ変換サンプルデータ

ひらがなカタカナ変換サンプルデータ


変換用のサンプルプログラムは以下の通りです。

#CSVファイルを開いてメールアドレスをチェックする

use strict;
use warnings;
use utf8;
binmode STDOUT, 'encoding(utf8)'; #Windows の場合は utf8 -> cp932

require 'csvutil.pl';

my ($fh_in, $fh_out);
open ($fh_in, '<:encoding(cp932)', 'data.csv')
	or die "ERROR: open: data.csv: $!
"
	;
open ($fh_out, '>:encoding(cp932)', 'data_conved.csv')
	or die "ERROR: open: data_conved.csv: $!
"
	;

while(<$fh_in>){
	my @line = split(/, */, $_);
	$line[2] = &hira2kata($line[2]);
	print $fh_out join(',', @line);
}

close $fh_in;
close $fh_out;

関数ファイルを読み込む require文字コードを指定してのファイルオープンの方法を使っています。

まとめと応用


今回は、データ中の表記の揺れを修正するためのPerlの正規表現を覚えました。このようにデータを整形する事を「正規化」と呼びます。サンプルプログラムではCSVにまとまって保存されたデータの正規化を行いましたが、同じサブルーチンを使って、問合せフォームなどから入力がされた時に自動的に変換を行う事も可能です。


※記事内容は執筆時点のものです。最新の内容をご確認ください。
※OSやアプリ、ソフトのバージョンによっては画面表示、操作方法が異なる可能性があります。