(Irr|R)egular Expressions

by @dankogai

セイキヒョウゲン?

それってえろい?

正規表現!

それってえらい!

「すべての魔女を、消し去りたい」

$universe =~ s/魔女//g;

正規表現さえ知っていれば、まどかも…

命賭けるな、コード書け。

「正規表現を知る前のバカな私を、たすけてあげてくれないかな?」

でも使いどころを間違えると…

こうなったり…

こうなったり。

「気まぐれで正規表現を使うなんて、そんなの私が許さない」

というわけで、今回は「正規表現の使い過ぎ」に関して注意を喚起。

$foo =~ /^(XXX|YYY)$/

http://mt.endeworks.jp/d-6/2008/03/neurotic-perl-hacker.html
if ($foo eq 'XXX' || $foo eq 'YYY')を if ($foo =~ /^(XXX|YYY)$/) に書き直したくなる

「それには及ばないわ」

ハッシュも…
my @pm
  = qw/homura mami sayaka kyoko madoka/;
my %is_pm = map { $_ => 1 } @pm;
if ($is_pm{$she}){
  # ...
}
スマートマッチも…
my @pm
  = qw/homura mami sayaka kyoko madoka/;
if ($she ~~ @pm){ # perl 5.10 or better
  # ...
}

あるんだよ。

メールアドレスの検証

検証なんて、あるわけない。

my $phpers_mailaddr =qr{
  ^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@]
  [a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$
};

だからといってこれでは…

my $rfc2822 = qr{
(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)
(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|
(?:"(?:\\[^\r\n]|[^\\"])*")))
\@
(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)
(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|
(?:\[(?:\\[\x01-\x09\x0B-\x0c\x0e-\x7f]|
[\x21-\x5a\x5e-\x7e])*\])))
}x;

わけがわからないよ

perldoc -q mail

use Regexp::Common

本当の正規表現と向き合えますか?

(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.]
(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.]
(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.]
(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))

use Regexp::Common

それはとっても嬉しいなって

use Regexp::Common;
my $re_ipv4 = $RE{net}{IPv4};

use Regexp::Assemble;

Alteration まじ女神

# こういうやつ
my $qb = /人◕‿‿◕人\;

Alteration まじ女神

# じゃなくてこう
my $puellae_magi =~
  qr/(?:homura|mami|sayaka|kyoko|madoka)/;

でも高い

こうすれば速くなるけど…

my $puellae_magi =~
  qr/(?:(?:homur|sayak)a|ma(?:doka|mi)|kyoko)/;

素手で出来たら魔女確定

…失礼。こっち

そこで Regexp::Assemble

use Regexp::Assemble;
my @puellae_magi = 
  qw/homura mami sayaka kyoko madoka/;
my $puellae_magi = do{
  my $ra = Regexp::Assemble->new;
  $ra->add($_) for @puellae_magi;
  $ra->re;
};

もう素手には頼らない

実はPerl 5.10以降のPerlは TRIE Optimization してくれる

けど、こういうことまではできない

use Regexp::Assemble;

my %analyze = (
    qr/きゅうべえ|キュゥべえ|Incubator/ => 'qb',
    qr/ほむら|ほむほむ/ => 'homura'
    # ...
);
my $re = Regexp::Assemble->new; 
$re->track;
$re->add(keys %analyze);
while (my $log = $logs->readline) {
    next unless $log->{ua} 
    # $matched には、matchの結果ではなく
    my $matched = $re->match($log->{ua}));
    # match した正規表現が入る。
    next unless defined $mached;
    my $pattern = $analyze{$matched};
    # …
}

use Regexp::Assemble;

s///sexsexsex…

そうはいっても、やっぱり正規表現は…

Perlの、最高のともだち

asin:4873113598

ご清聴ありがとうございました