『初めてのPerl』第8章 正規表現によるマッチ

ドット(.)をあらゆる文字にマッチさせる/s:

#!/usr/bin/env perl
use v5.12;
use warnings;
$_ = "I saw Barneyndown at the bowling alleynwith Frednlast night.n";
if (/Barney.*/) { # こっちはマッチしない
say "matched";
}
if (/Barney.*/s) { # sを付けると、.は改行文字にもマッチするようになる
print "That string mentions Fred after Barney!n";
}

正規表現中に空白文字を含める/x:

#!/usr/bin/env perl
use v5.12;
use warnings;
$_ = "I saw Barney down at the bowling alley with Fred last night.";
if (m{
Barney
.* # 正規表現中のコメントは空白文字とみなされる
Fred
}x) {
print "That string mentions Fred after Barney!n";
}

括弧による文字列のキャプチャと、その制御:

#!/usr/bin/env perl
use v5.12;
use warnings;
my $names = 'Fred or Barney';
# ()で囲った範囲の文字列はキャプチャされ、後方参照や変数での再利用ができる
# (?: で始まる括弧では文字列はキャプチャされない
if ($names =~ m/(w+) (?:and|or) (w+)/) {
say "I saw $1 and $2"; # ()でキャプチャした文字列は$1,$2...で呼び出せる
}
# Perl5.10以降では、
# (?<ラベル>で始まる括弧でキャプチャした文字列は、
# %+というハッシュに記録され、$+{ラベル}で呼び出せる
if ($names =~ m/(?<name1>w+) (?:and|or) (?<name2>w+)/) {
say "I saw $+{name1} and $+{name2}";
}

名前付きキャプチャの後方参照:

#!/usr/bin/env perl
use v5.12;
use warnings;
my $names = 'Fred Flinstrone and Wilma Flinstrone';
# 名前付きキャプチャの後方参照には g{ラベル} という記法を使う
if ($names =~ m/(?w+) and w+ g{last_name}/) {
say "I saw $+{last_name}";
}

自動マッチ変数(括弧でキャプチャしなくても自動でセットされる変数):

#!/usr/bin/env perl
use v5.12;
use warnings;
if ("Hello there, neighbor" =~ /sw+,/) { # 括弧でキャプチャしていない
# &`: マッチした部分より前にあるもの
# $&: マッチした部分
# &': マッチした部分より後ろにあるもの
# 自動マッチ変数3つを連結すると、元の文字列を復元できる
say "That was ($`)($&)($')";
}

※自動マッチ変数は、次のマッチが実行されるまで値を保持する
※自動マッチ変数を使うと、プログラム全体の正規表現が少しだけ遅くなる

自動マッチ変数を一部だけ使用する/p(Perl 5.10以上):

#!/usr/bin/env perl
use v5.12;
use warnings;
if ("Hello there, neighbor" =~ /sw+,/p) {
# ${^PREMATCH} : マッチした部分より前にあるもの
# ${^MATCH} : マッチした部分
# ${^POSTMATCH} : マッチした部分より後にあるもの
say "That was (${^PREMATCH})(${^MATCH})(${^POSTMATCH})";
}

感想

Perlの正規表現は機能が豊富で、新しい機能もどんどん追加されている、という話は聞いていたけど、確かにその通りだった。Perlでは、初心者本でここまで詳細に正規表現を解説するのか! と驚いた。

あと、名前付きキャプチャについて、「PHPでも使えないかな」と思って試してみたら、使えた:

<?php
if (preg_match('/(?<hoge>hoge)/', 'hogefuga', $matched)) {
echo  $matched['hoge'], PHP_EOL; // hoge
}

教訓:他言語を学ぶことで、メインで使ってる言語についても、より深く学ぶことができる。

コメントを残す

コメントを残す