masatoの日記

やっていきます

Perlで正規表現を使って日本語の文字列にマッチさせる

やりたいこと

日本語の文字列に任意の文字列が含まれるかどうか判定したい。

二通りのやりかたを書く。

正規表現でマッチさせる

use Encode qw/encode/;

# source text
my $str = 'メッセージ”通信エラー”が表示されます。';
my $p = '通信エラー';

$p = encode('utf8', $p);
$str = encode('utf8', $str);

if ($str =~ m/$p/) { # マッチをトライ
    print "Found it!!!";
}

index関数を使う

あるいは、index関数を使って任意の文字列が含まれるかどうかを判定できる。

## index function
if (index($str, $p) >=0) {
    print "Found it!!!\n";
}

メタ文字にマッチさせたいときは、\エスケープしてもよいが、quotemetaすれば自動でエスケープされて便利。

## quotemeta
my $qp = quotemeta $p;
if ($str =~ s/$qp/Communication fault/) {
    print "Replaced: $str\n";
}

名前付きキャプチャを使って複雑なマッチに対処する

正規表現でキャプチャしたグループは、$1, $2...という変数で参照できる。 だけどごちゃごちゃした文字列をキャプチャして参照したいときは、名前で参照できたほうが簡単だ。

キャプチャしたグループに名前をつけるには、(?<tag>)というふうに書く(tagは任意の名前)。 名前付きキャプチャの結果は%+というハッシュに入る。個別の要素を、指定した名前をキーとして参照できる。つまり、$+{tag}という具合。

my $line = 'no:1234 item_name:banana price:160 qty:8';
$line =~ /\Ano:(?<no>\d+)\s*
              item_name:(?<item_name>.*)\s*
              price:(?<price>\d+)\s*
              qty:(?<qty>\d+)\s?*
              \z/x;

print "番号:$+{no}\n";
print "品名:$+{item_name}\n";
print "価格:$+{price}\n";
print "数量:$+{qty}\n";

# 番号:1234
# 品名:banana
# 価格:160
# 数量:8