--- title: 『新版Perl言語プログラミングレッスン入門編』第8章 author: kazu634 date: 2008-02-25 wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3771;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - Perl - Programming ---

 「もっと正規表現」というセクション名だよー

簡単なマッチ

 「=~」という演算子を用いて色々とごにゃごにゃする。

$str =~ /\d+/

とすると、数字列が存在すればTrueを、存在しなければFalseを返す。

マッチした範囲を取り出したい!

 特殊な変数「$&」を用いると、マッチした範囲を取り出すことができる。

use strict;
use warnings;
my $str = "The price is 300yen.";
if ($str =~ /\d+/) {
print "$& is the number\n";
}

この場合は、「$&」には「300」が入る。

マッチした範囲を複数取り出す!

 特殊変数「$&」はマッチした部分を取り出すのに役に立ちます。こいつを使うのはマッチさせたい箇所が一つだけのとき。もし文字列の中でマッチさせたい部分が複数ある時は$1, $2, $3, …, $nを用います。$1, $2, $3, …には正規表現の中で()に囲まれた部分が自動的に設定されます。

use strict;
use warnings;
my $str = "168, 57, 37";
if ($str =~ /(\d+), (\d+), (\d+)/) {
my $height = $1;
my $weight = $2;
my $age = $3;
print "Height: $height\n";
print "Weight: $weight\n";
print "Age: $age\n";
}

こいつの別な書き方としては

use strict;
use warnings;
my $str = "168, 57, 37";
if ($str =~ /(\d+), (\d+), (\d+)/) {
my ($height, $weight, $age) = ($1, $2, $3);
print "Height: $height\n";
print "Weight: $weight\n";
print "Age: $age\n";
}

上の二つのプログラムは「コンマで区切られた数字列を取り出す」という見方で作られている。仮に(数字列に限らず)「コンマで区切られた文字列を取り出す」という視点に立てば次のようになる。

use strict;
use warnings;
my $str = "168, 57, 37";
my ($height, $weight, $age) = split(/,/, $str);
print "Height: $height\n";
print "Weight: $weight\n";
print "Age: $age\n";

ちなみに複数マッチするように正規表現をくんだとき、「$& = $1」である。また「$1, $2, $3, …, $n」は左括弧の順で代入されていく。

\1という表記

 \1は正規表現の中で用いて、直前の正規表現と同じものを指します。例えば「/[bcdfghjklmnpqrstvwxyz]([aeiou])\1」と表記することで、

などにマッチする。「()」は必須。

変数$_とパターンマッチ

 単に「/^From:/」と書くと、デフォルト変数の$_がパターンマッチの対象になる。

簡単な置換

 基本は

s/置換前/置換後/

という形。例としては

use strict;
use warnings;
my $str = "How I wonder what you are.\n";
$str =~ s/what/who/;
print $str;

こいつはマッチするのが複数あっても、最初の一つだけしか置換しない。全部置換させたい場合は「s/置換前/置換後/g」と表記する。

特殊変数$&を置換で使う

 言うまでもなく「$&」はマッチした部分を指す。

use strict;
use warnings;
my $str = "How I wonder what you are.\n";
$str =~ s/what/\*$&\*/;
print $str;

こいつだと、マッチした部分を「*」で囲んでいる。

マッチした部分の削除

 「s/置換前//」と表記する。

特殊変数$1, $2, $3, …の利用

 マッチの時と同じように、()でくくったパターンにマッチした文字列を左括弧の順に$1, $2, $3, … という特殊変数で得ることができます。

use strict;
use warnings;
my $str = "The price is 300yen. The distance is 120km.\n";
$str =~ s/((\d+)([A-Za-z]+))/$2<$3>/g;
print $str;

式を評価する修飾子 /e

 修飾子「/e」をつけると、置換後の部分をPerlの式として評価(計算)してくれます。

use strict;
use warnings;
my $str = "How I wonder what you are.\n";
$str =~ s/\w+/ucfirst($&)/eg;
print $str;

メタ文字 \b

 正規表現でメタ文字 \b は、単語の境界にマッチするものです。

tr///による置換の例

use strict;
use warnings;
my $str = "How I wonder what you are.\n";
$str =~ tr/A-Za-z/a-zA-Z/;
print $str;

tr///の使い方

 ここで使われている「tr///」は、次のような形式で用い、文字を置換したり削除したりするのに用いられます。使用例は

tr/置換元の文字リスト/置換先の文字リスト/オプション

という感じ。tr///の戻り値は置換(あるいは削除)した文字数になります。

tr///の慣用句(1): 英大文字の数を数える

my $str = 'This is Perl.';
my $count = ($str =~ tr/A-Z/A-Z/);
print $count, "\n";

tr///の慣用句(2): $nameを$unameに代入し、$unameの方だけをすべて大文字にする

my $name = 'Hiroshi';
(my $uname = $name) =~ tr/a-z/A-Z/;
print "\$name = $name\n";
print "\$uname = $uname\n";

tr///の慣用句(3): 英小文字を削除する

my $str = 'Yahoo!JAPAN & Yahoo! (USA)';
$str =~ tr/a-z//d;
print "|$str|\n";

tr///の慣用句(4): 英数字以外を1個のスペースに置換する

my $str = 'Yahoo!JAPAN & Yahoo! (USA)';
$str =~ tr/A-Za-z0-9/ /cs;
print "|$str|\n";