perl6 regex programming with rakudo

Post on 11-Jun-2015

2.777 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

YAPC::Asia 2010 Tokyo Day 2 (Yoshinori TAKESAKO)

TRANSCRIPT

Perl 6 正規表現プログラミング楽土入門

サボウズ・ラボ株式会社

竹迫 良範

<takesako@shibuya.pm.org>

2009/04/06 Cybozu University 2

自己紹介

Shibuya Perl Mongers 2代目リーダー

いまここ

2009/04/06 Cybozu University 4

My Parrot

My pretty Parrot (Cockatiel) 可愛的小奧姆

Moshi-moshi ?

My Parrot can say “Hello” when the telephone rang.

另外的 Parrot 算術擅長

Parrot Assembler (PASM)

PASM

set I1, 33set I2, 5mod I3, I1, I2if I3, REMA print "5 is an integer divisor of 33" branch DONE

REMA: print "5 divides 33 with remainder " print I3

DONE: print "¥n" end

33÷5=6、余り2 を計算する

(5 into 33 is 6, remainder 2)

Perl6 の実装方針(最初の戦略)

Parrot

Perl6 を Parrot で書く

Perl5 を Parrot で動くようにする (Ponie Project)

2009/04/06 Cybozu University 8

Perl 5 is alive.

But …

Perl 5 “Hello, world!”

package Earth;sub Greet{

%_=('Y','~');$_='$;=!(Middle

Earth.age~~~<Eart~~~~~~~~~~~~~h

.age)?!(defined$ti~~~~~~~~~~~mez~~~On

e[2])?!(push@time~~~~~~~~~~~~~~~~Zone,loc

~altime())?rotation?~~~~~~~~~~~~~q~~?The Worl

~~d?:q:[¥w]::q=[¥~~~~~~~~~~~~~~~~~d~a-f]=:q?..~~

~~~?:q:.:;"42b3d3~~~~~~~~~~~~~~~~~~~~~728656c6c6f6

~~~~~0277f627c64672~~~~~~~~~~~~~~~~~~~~~b3072796e647

~~~~~~~42b3b3rg7d"=Ym~~~~~~~~~~~~~~~~~~~¥$;~~*¥;p~~~~u

~~~~~~~~~sh@_,$&;bless~~~~~~~~~~~~~~~~~~~~~~~~~$c~~~~~~~

~~~~~~~~~o~ntine~~~~~nt~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~s=¥~~~~~~~$~~~~~~~~~~~~~~~~~~~~~~~pangaea~~~~

~~~~~~~~~~~~~~~;{l~~~~~~~~~~~~~~~~~~~~~~~~~~~~ocal@_;local$;

~~~~~~~~~~~~~~~~~="o~~~~~~~~~~~~~~~~~~~~~~~~~cean";$^A=(defi

~~~~~~~~~~~~~~~~~~~n~~~~~~~~~~~~~~~~~~~~~~~~~ed$continents)?

~~~~~~~~~~~~~~~~~~~(vec(~~~~~~~~~~~~~~~~~~~~~~$;, YYsplit(¥'

~~~~~~~~~~~~~~~~~¥',${¥$;}~~~~~~~~~~~~~~~~~~~~~~)%3,YYsplit(

~~~~~~~~~~~~~~~~q??,$;)**2-~~~~~~~~~~~~~~~~~~~~~~(($;=Ytr/oa

~~~~~~~~~~~~~~~~eiu//)**2))=~~~~~~~~~~~~~~~~~~~~~~=28160)?q:

~~~~~~~~~~~~~~~~~.::q?!?:¥'?~~~~~~~~~~~~~~~~~~~~~~¥';}$^A=Ys

~~~~~~~~~~~~~~~~:¥Q.¥E:pack(~~~~~~~~~~~~~~~~~~~~~~¥'h*¥',j

~~~~~~~~~~~~~~~~~oin(q(),~~~~~~~~~~~~~~~~~~~~~~~grep{$_=

~~~~~~~~~~~~~~~~~~Ym,$,,}~~~~~~~~~~~~~~~~~~~~~~~split("

~~~~~~~~~~~~~~~~~",@_~~~~~~~~~~~~~~~~~~~~~~~~~~[0]))

~~~~~~~~~~~~~~~~):e~~~~~~~~~~~~~~~~~~~~~~~~~~~gexe

~~~~~~~~~~~~~~~;$d~~~~~~~~~~~~~~~~~~~~~~~~~~~="s

~~~~~~~~~~~~~~ort~~~~~~~~~~~~~~~~~~~~~~~~~~<=

~~~~~~~~~~~~>,~~~~~~~~~~~~~~~~~~~~~~~~~~YY

~~~~~~~~~~~@_~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~"~~~~~~~~~~~~~~~~~~~';;

s,(~|¥r|¥n|¥s),,g;s.Y.¥x7e.g;

eval};Greet;'the world';

http://www.perlmonks.org/index.pl?node_id=329174 by jbware on Feb 15, 2004 at 21:08 UTC (#329174=obfuscated)

Unreadable

Perl5→読みにくいプログラムを量産し続けるPerl5

Readable

Perl6!読みやすいプログラムを書けるPerl6になる!

Perl 6 では・・・

ね、簡単でしょ?

say "Hello, world!";

2009/04/06 Cybozu University 13

Perl 6on

Parrot

這個 Parrot 能說各種各樣的語言

O’REILLY

NOT’REALLY

2000

Perl6 言語仕様 (language specification)

1. Apocalypse(黙示録)

Larry Wall が Perl6 のデザンについて語る

Perl6 の歴史的な文書(33個のRFCがベース)

2. Exegesis(注釈)

Perl6 を用いたサンプルコードや Perl5 との比較

黙示録を Damian Conway が詳細に解説

3. Synopsis(概要)

Perl6 の最新の言語仕様が書かれている

黙示録のダジェスト版

Why Perl 6 ? (モチベーション)

Perl 5 は・・・場当たり的な拡張を繰り返し

既に Perl5 のコードは理解不能な領域にC でゴリゴリ 職人技 (needs more C hacker)

Perl 6 の目指す方向せめて OO らしく

他の言語で良いところは取り入れよう

後方互換性は無視

コンパラと実行環境の分離Parrot で VM 化

No more C hacker

all your language are belong to us

- Project Perl 6 -

Second System Syndrome (The Mythical Man-Month)

2度目にデザンするシステムは失敗作になりやすい説

1度目のデザンは自分の能力を把握していないので慎重に

3度目のデザンは何が普遍的で何が特殊なものか分かるので正確に作ることができる

しかし2度目のデザンでは、最初のデザンで抑えたゕデゕ・装飾を思い切り詰め込んでしまうので失敗作になりやすい

人月の神話―狼人間を撃つ銀の弾はない

ISBN: 4894716658→ Perl6 は構想10年!

・・・

2005

救世主 Pugs の登場

Pugs = Perl6 User’s Golfing System

Yet another Perl6 implementation

→ Perl6 が動いた!2005/02/06 (1|2)+(3|4)→(4|5|6)

Audrey Tang (唐鳳)

CPAN界隈で有名

PARの作者

1981年生まれ

国籍:台湾

http://en.wikipedia.org/wiki/Audrey_Tang

高橋メソッドを世界に輸出した人

Perl6(Pugs)を Haskell で実装した天才プログラマー

Pugs の拡張性

powered by

Haskell

2010

待望の Perl6 – Rakudo Star リリース!

http://rakudo.org/

http://github.com/rakudo/star/downloads

Get your own Parrot!

34

5秒でわかる Perl 6

メソッドを -> ではなく . で書けるようになった

Perl 5

$obj->method();

Perl 6

$obj.method();

→ これで Perl も立派なOO言語の仲間入り!

36

The End

終了

Perl 6 で失ったもの ~後方互換性~

文字列の連結 .(ドット)→ ~(チルダ)に

Perl5

# メソッド呼び出し

$obj->method();

sub func { return "x"; }

# 文字列の連結

my $a = "str";my $b = $a.func();

Perl6

一時期 ” _ ” という案もあったが…スペース入れるのが面倒

# メソッド呼び出し

$obj.method();

sub func { return "x"; }

# 文字列の連結

my $a = "str";my $b = $a~func();

subst 文字列の置換

Rakudo/bin/ufo より

sub path-to-module-name($path) {$path.subst(/^'lib/'/, '') ¥

.subst(/¥.pm6?$/, '') ¥

.subst('/', '::', :g) ;}

OO

Perl 5

Sigils

$ @ %

配列とハッシュのゕクセス方法が変更

はじめての人にもわかりやすく

変数のプレフゖクス $@% ルールが変更

Perl5 Perl6

my @array = (1, 2, 3);my %hash = ('a'=> 1);

# 配列のメンバにアクセスmy $x = $array[0];

# ハッシュのメンバにアクセスmy $y = $hash{'a'}

my @array = (1, 2, 3);my %hash = ('a'=> 1);

# 配列のメンバにアクセスmy $x = @array[0];

# ハッシュのメンバにアクセスmy $y = %hash{'a'}

Perl 5 の変数(sigils rules)

scalar array hash

------- ------ -------

$s @a %h

$$s $a[0] $h{'?'}

$s->foo ☹ ☹

Perl 6 の変数(Sigils rule)

scalar array hash

------- ------ -------

$s @a %h

$$s @a[0] %h<?>

$s.foo @a.foo %h.foo

() 括弧省略

if, for, while, do ブロックでの(括弧省略)

キータプの量が少なくなった

Perl5 Perl6

if ($a eq $b) {print "a=b¥n";

}

while ($i > 0) {$i--;

}

if $a eq $b {say "a=b";

}

while $i > 0 {$i--;

}

Perl5 Perl6

# スペースなしprint(1+2)*3;

# スペースなしprint(1+2)*3;

(例)

スペースのあり/なしで実行結果が違う

# スペースありprint (1+2)*3;

# スペースありprint (1+2)*3;

→ 実行結果: 3 → 実行結果: 3

→ 実行結果: 3 → 実行結果: 9

Neko operator(範囲演算子)

Damian Conway氏が OSCON2005 で発音

http://www.rubyist.net/~matz/20050803.html

末尾を含まない「..^」

先頭を含まない「^..」

先頭と末尾を含まない「^..^」

Perl6

my @a = (1..^5); # (1,2,3,4)my @b = (1^..5); # (2,3,4,5)my @c = (1^..^5); # (2,3,4)

ネコ演算子って・・・ちょwおまwww

neko operator

^..^

ネコ耳モード♪

Damian Conway 日本の漫画好き?

http://www.amazon.co.jp/dp/4847034864/

49

Please give me!

zip でくれ

使用例:zip でくれ

便利な zip

2つの配列を同時にループ

順番を保存した重複する key と value の表現

Perl5 Perl6

my @key = ("x", "y", "x");my @value = (1, 2, 3);

for (my $i=0; $i<@key; $i++) {my $a = $key[$i];my $b = $value[$i];print "key:$a; value:$b¥n";

}

my @key = ("x", "y", "x");my @value = (1, 2, 3);

for zip(@key,@value) -> $a,$b {print "key:$a; value:$b¥n";

}

実際には Z operator が使える

Rakudo では zip ではなく Z 演算子が実装

(1,2) Z (3,4) (1,3, 2,4)

Rakudo Perl6

my @key = ("x", "y", "x");my @value = (1, 2, 3);

for @key Z @value -> $a,$b {print "key:$a; value:$b¥n";

}

my @key = ("x", "y", "x");my @value = (1, 2, 3);

for zip(@key,@value) -> $a,$b {print "key:$a; value:$b¥n";

}

Piping operators(<==, ==>)

Perl6

@result = map { floor($^x / 2) }

grep { /^ ¥d+ $/ }

@data;

@result <== map { floor($^x / 2) }

<== grep { /^ ¥d+ $/ }

<== @data;

@data ==> grep { /^ ¥d+ $/ }

==> map { floor($^x / 2) }

==> @result;

// 演算子(err 演算子)

左辺が undef のときのみ右辺を評価

// defined or

Perl5 でありがちなバグを回避

0(ゼロ) や ”” (空文字列)の扱い

それぞれ || → or, // → err に対応

Perl5 Perl6

$num = shift @ARGV || 1;

$bar = func() or die;

$num = shift @ARGS // 1;

$bar = func() err die;

// は C言語で単一行コメント(PL/I起源)

/* C comment style */// #include <stdio.h>

必ず Syntax Error になる記号

# Shell - single line comment

# Perl - single line comment

JavaScript // problem

var r = new RegExp(“pattern”);

var r = /pattern/;

これは何?

//

// start a single-line comment.

To specify an empty regular expression,

use /(?:)/

57

Perl 5 Perl 6

正規表現

別の言語

Perl5 正規表現 Perl6 Regex で変わるもの

1. 基本パターン繰り返し *+? と選択 |

2. マッチ演算子文字列のパターンマッチ m//スマートマッチ演算子 ~~文字列の置換 s///

3. 修飾子複数行モード/m 修飾子の廃止文字列の先頭「¥A」末尾「¥z」の廃止スペースとコメントが自由に挿入できるモード/x がデフォルトに単一行モード/s の廃止 /e 修飾子の廃止新しい修飾子の書き方

Perl5 正規表現 Perl6 Regex で変わるもの

4. キャプチャ

キャプチャ括弧(…)と後方参照

キャプチャを伴わない括弧 […]

5. メタキャラクタ

文字クラスの定義 <[a-z]>

定義済み文字クラスの参照 <class>

変数展開 <$var>

文字列 <'string'> のリテラル展開

文字列配列 @strings のリテラル展開

Perl5 正規表現 Perl6 Regex の未来

6. クロージャ

コードの実行 {code}

マッチ失敗 {fail}

繰り返し範囲 **{n..m}

7. ルール

rule

grammar

61

1. 基本パターン

62

繰り返し *+? と選択 |

Perl 5 Perl 6

/x*/ # xが0個以上繰り返し

/y+/ # yが1個以上繰り返し

/z?/ # zが0個以上1個以下

/foo|bar/ # fooまたはbar

/x*/ # == Perl 5

/y+/ # == Perl 5

/z?/ # == Perl 5

/foo|bar/ # == Perl 5

$_ = "aaa bbb ccc foo moo zoo";

if (/aaax*/) { print "ok¥n" }

if (/b+/) { print "ok¥n" }

if (/cccc?/) { print "ok¥n" }

if (/foo|bar|baz/) { print "ok¥n" }

$_ = "aaa bbb ccc foo moo zoo";

if /aaax*/ { say "ok" }

if /b+/ { say "ok" }

if /cccc?/ { say "ok" }

if /foo|bar|baz/ { say "ok" }

63

2. マッチ演算子

文字列のパターンマッチ m//

Perl 5 Perl 6

/pattern/

m/pattern/

m{pattern}

qr/pattern/

$_ = "This is a pen.";

if (/This/) { print "ok¥n" }

if (m/pen/) { print "ok¥n" }

if (m{pen}) { print "ok¥n" }

unless (/not match/) { print "ok¥n" }

if ($_ =~ qr/pen/) { print "ok¥n" }

$_ = "This is a pen.";

if /This/ { say "ok" }

if m/pen/ { say "ok" }

if m{pen} { say "ok" }

unless /not match/ { say "ok" }

if ($_ ~~ rx/pen/) { say "ok" }

/pattern/

m/pattern/

m{pattern}

rx/pattern/ または regex{pattern}

スマートマッチ演算子 ~~

Perl 5 Perl 6

$str =~ /pattern/$str !~ /pattern/

$str ~~ /pattern/$str !~~ /pattern//pattern/ ~~ $str/pattern/ !~~ $str

my $str = "This is a pen.";

if ($str =~ /This/) { print "ok¥n" }

if ($str =~ m/pen/) { print "ok¥n" }

## (m/pen/ =~ $str) とは書けない

if ($str !~ /not match/) { print "ok¥n" }

unless ($str ~~ /not match/) { print "ok¥n" }

my $str = "This is a pen.";

if $str ~~ /This/ { say "ok" }

if $str ~~ m/pen/ { say "ok" }

if m/pen/ ~~ $str { say "ok" }

if $str !~~ /not match/ { say "ok" }

unless $str ~~ /not match/ { say "ok" }

66

3. 修飾子

複数行モード/m 修飾子の廃止

Perl 5 Perl 6

/^ pattern $/m /^^ pattern $$/

my $lines = "aaa¥nbbb¥nccc¥n";

if ($lines =~ /^b/m) { print "ok¥n" }

if ($lines =~ /bb$/m) { print "ok¥n" }

if ($lines =~ /^bbb$/m) {

print "ok¥n";

}

my $lines = "aaa¥nbbb¥nccc¥n";

if $lines ~~ /^^b/ { say "ok" }

if $lines ~~ /bb$$/ { say "ok" }

if $lines ~~ /^^bbb$$/ {

say "ok" ;

}

正規表現の修飾子/mで「^」と「$」のマッチ規則が変わる

文字列の先頭「¥A」末尾「¥z」の廃止

Perl 5 Perl 6

/¥A pattern ¥z/ /^ pattern $/

my $str = "abracadabra";

if ($str =~ /¥Aabra/) { print "ok¥n" }

if ($str =~ /abra¥z/) { print "ok¥n" }

if ($str =~ /¥Aabracadabra¥z/) {

print "ok¥n" ;

}

my $str = "abracadabra";

if $str ~~ /^abra/ { say "ok" }

if $str ~~ /abra$/ { say "ok" }

if $str ~~ /^abracadabra$/ {

say "ok" ;

}

複数行モード/m に影響しないゕンカー記号「¥A」「¥z」

スペースとコメントが自由に挿入できるモード/x がデフォルトに

Perl 5 Perl 6

/ pattern1 # コメントをここに書く

pattern2 pattern3

/x

/ pattern1 # コメントをここに書く

pattern2 pattern3

/

my $str = "abracadabra";

if ( $str =~ / abra # ゕブラca # カ

d abra # ダブラ/x # 終了

) { print "ok¥n" }

if ($str =~ / abra cad abra /x) { print "ok¥n" }

my $str = "abracadabra";

if ( $str ~~ / abra # ゕブラca # カ

d abra # ダブラ/ # 終了

) { say "ok" }

if $str ~~ / abra cad abra / { say "ok" }

スペースのマッチ

Perl 5 Perl 6

/¥ /x

/¥Q ¥E/x

/[ ¥t¥r¥n]/x

/[ ¥t¥r¥n]+/x

/¥ /

/<' '>/

/<space>/

/<ws>/

my $str = "This is¥ta ¥n pen.";

if ($str =~ / This ¥ is /x)

{ print "ok¥n" }

if ($str =~ / This ¥Q ¥E is /x)

{ print "ok¥n" }

if ($str =~ / is [ ¥t¥r¥n] a /x)

{ print "ok¥n" }

if ($str =~ / a [ ¥t¥r¥n]+ pen /x)

{ print "ok¥n" }

my $str = "This is¥ta ¥n pen .";

if $str ~~ / This ¥ is /

{ say "ok" }

if $str ~~ / This <' '> is /

{ say "ok" }

if $str ~~ / is <space> a /

{ say "ok" }

if $str ~~ / a <ws> pen /

{ say "ok" }

単一行モード/s の廃止

Perl 5 Perl 6

/./s # どんな文字(改行を含む)

/./ # どんな文字も(改行は除く)

/[¥x0D¥x0A]|¥x0D¥x0A/

/./ # 改行を含むどんな文字

/¥N/ # 改行以外のどんな文字も

/¥n/ # どんな端末の改行にもマッチ

my $c = '/************************ This is a C comment ************************/#include <stdio.h>/* first */main() { printf("C"); }';

if ($c =~ m/(¥/¥*.+?¥*¥/)/) {if ($1 eq "/* first */") { print "ok¥n" }

}if ($c =~ m/(¥/¥*.+?¥*¥/)/s) {

my $lines = $1;if ($lines =~ /comment/) { print "ok¥n" }

}

my $c = '/************************ This is a C comment ************************/#include <stdio.h>/* first */main() { printf("C"); }';

if $c ~~ m{( ¥/¥* ¥N+? ¥*¥/ )} {if $0 eq "/* first */" { say "ok" }

}if $c ~~ m{( ¥/¥* [.|¥n]+? ¥*¥/ )} {

my $lines = $0;if $lines ~~ /comment/ { say "ok" }

}

/e 修飾子の廃止 どこでも {code}

Perl 5 Perl 6

s/pattern/code/e s/pattern/{code}/

sub cm2inch {

my ($cm) = @_;

sprintf('%.01f-inch', $cm / 6.5);

}

my $floppy = "3.5-inch FDD";

if ($floppy =~ s/(¥d+¥.¥d+)-inch/{ sprintf('%.02f-cm',

$1 * 6.5) }/ex) {

if ($floppy eq "22.75-cm FDD") { print "ok¥n" }

if ($floppy =~ s/(¥d+¥.¥d+)-cm/{ &cm2inch($1) }/ex) {

if ($floppy eq "3.5-inch FDD") { print "ok¥n" }

}

}

sub cm2inch($cm) {

sprintf('%.01f-inch', $cm / 6.5);

}

my $floppy = "3.5-inch FDD";

if $floppy ~~ s/(¥d+¥.¥d+)-inch/{ sprintf('%.02f-cm', $0 * 6.5) }/ {

if $floppy eq "22.75-cm FDD" { say "ok" }

if $floppy ~~ s/(¥d+¥.¥d+)-cm/{ &cm2inch($0) }/ {

if $floppy eq "3.5-inch FDD" { say "ok" }

}

}

cf. Acme::Hyde(単位変換) on CPAN

新しい修飾子の書き方

Perl 5 Perl 6

m/pattern/i

s/pattern/replace/ig

m/:i pattern/

s:g/pattern/replace/

my $imas = "とかしつくして";

if ($imas =~ s/し/ち/g) {

if ($imas eq "とかちつくちて") {

print "ok¥n";

}

}

my $imas = "とかしつくして";

if $imas ~~ s:g/し/ち/ {

if $imas eq "とかちつくちて" {

say "ok";

}

}

74

4. キャプチャ

キャプチャ括弧(…)と後方参照

Perl 5 Perl 6

(…)〃¥1〃¥2〃¥3… (…)〃$0〃$1〃$2…

my $str = "abracadabra";

if ($str =~ /(a)br¥1c/) { print "ok¥n" }

if ($str =~ /(ab)racad$1ra/) { print "ok¥n" }

if ($str =~ /(a)(b)r$1c$2d$2$2ra/) {

print "ok¥n" ;

}

if ($1 eq "a") { print "ok¥n" }

if ($2 eq "b") { print "ok¥n" }

my $str = "abracadabra";

if $str ~~ /(a)br$0c/ { say "ok" }

if $str ~~ /(ab)racad$0ra/ { say "ok" }

if $str ~~ /(a)(b)r$0c$0d$0$1ra/ {

say "ok" ;

}

if ($0 eq "a") { say "ok" }

if ($1 eq "b") { say "ok" }

日本円¥廃止

ドル$決済でゼロスタート

括弧(…)でキャプチャして、同じ正規表現内で後方参照する

【覚え方】

キャプチャを伴わない括弧 […]

Perl 5 Perl 6

(?:pattern) [pattern]

my @domain = ( "shibuya.pm.org",

"shibuya.pl" ,

"shibuyajs.org" ,

);

for (@domain) {

if (/^(¥w+)(?:¥.|-)?(js|pm|pl)(?:.org)?$/)

{

print "Hello, $1 $2 !¥n";

}

}

my @domain = ( "shibuya.pm.org",

"shibuya.pl" ,

"shibuyajs.org" ,

);

for @domain {

if /^(¥w+) [¥.|¥-]? (js|pm|pl) [.org]? $/ {

say "Hello, $0 $1 !";

}

}

ドメン名からコミュニテゖ名を判断し "Hello, shibuya pm !" と挨拶する

77

5. メタキャラクタ

文字クラスの定義 <[a-z]>

Perl 5 Perl 6

[abc]

[a-z]

[^xyz]

[B-Y]

<[abc]>

<[a-z]>

<-[xyz]>

< <[A-Z]> - <[AZ]> >

my @files = ("Jcode.pm", "Encode.pm", "jcode.pl");

foreach (@files) {

if (/ ( (?:J|En|j) code ¥. p[ml]) /x ) {

if ($_ eq $1) { print "ok¥n" }

}

}

my @files = ("Jcode.pm", "Encode.pm", "jcode.pl");

for @files {

if / ( [J|En|j] code ¥. p<[ml]> ) / {

if $_ eq $0 { say "ok" }

}

}

"Jcode.pm", "Encode.pm", "jcode.pl" のどれにもマッチする正規表現

文字クラスの定義 <[a-z]>

Perl 5 Perl 6

¥x20 # 空白1文字¥s+ # 連続したスペース¥. # ドット

[[:digit:]] # [0-9][[:upper:]] # [A-Z][[:lower:]] # [a-z][[:alpha:]] # [A-Za-z][[:alnum:]] # [A-Za-z0-9]

<space> # 空白1文字<ws> # 連続したスペース<dot> # ドット ※ <lt>, <gt><digit> # 数字<upper> # 英大文字<lower> # 英小文字<alpha> # ゕルフゔベット<alnum> # ゕルフゔベットと数字

$_ = "123 abc ¥t 456 ijk ¥t 789 XYZ";

if (/ ([0-9]+) ¥ ([A-Za-z]+) /x) {

if ($1 eq "123" && $2 eq "abc") { print "ok¥n" }

}

if (/ ([A-Za-z]+) ¥s+ ([0-9]+) /x) {

if ($1 eq "abc" && $2 eq "456") { print "ok¥n" }

}

$_ = "123 abc ¥t 456 ijk ¥t 789 XYZ";

if / (<digit>+) ¥ (<alpha>+) / {

if $0 eq "123" && $1 eq "abc" { say "ok" }

}

if / (<alpha>+) <ws> (<digit>+) / {

if $0 eq "abc" && $1 eq "456" { say "ok" }

}

変数展開 <$var>

Perl 5 Perl 6

/ $var /x / <$var> /

my $var = "(This|That) is a (pen|book)";

my $text1 = "This is a pen";

my $text2 = "That is a book";

if ($text1 =~ /$var/) {

print "ok¥n";

}

if ($text2 =~ /$var/) {

print "ok¥n";

}

my $var =

"(This|That)<space>is<space>a<space>(pen|book)";

my $text1 = "This is a pen";

my $text2 = "That is a book";

if ($text1 ~~ m/<$var>/) {

say "ok";

}

if ($text2 ~~ m/<$var>/) {

say "ok";

}

文字列 <'string'> のリテラル展開

Perl 5 Perl 6

¥Q$var¥E

¥Qstring¥E

¥$¥Qstring¥E

$var

<'string'>

<'$string'>

my $err = "Can't locate Boofy.pm in ¥@INC";

my $soozy = "Boofy.pm";

if ($err =~ /¥Q$soozy¥E/x) {

print "ok¥n";

}

if ($err =~ /¥@INC/x) {

print "ok¥n";

}

my $err = "Can't locate Boofy.pm in ¥@INC";

my $soozy = "Boofy.pm";

if $err ~~ /$soozy/ {

say "ok";

}

if $err ~~ /<'@INC'>/ {

say "ok";

}

文字列配列 @str のリテラル展開

Perl 5 Perl 6

$target ~~ / (?: ¥Q$str[0]¥E |

¥Q$str[1]¥E | … ) /x

$target ~~ / @str /

my @str = ("orz", "OTL", "_|~|-O");

my $food = "pasta mista, peperini,

capellini tagliati,

orzi piccoli, stelline.";

if ($food =~ /(?: ¥Q$str[0]¥E

| ¥Q$str[1]¥E

| ¥Q$str[2]¥E )/x)

{

print "ok¥n";

}

my @str = ("orz", "OTL", "_|~|-O");

my $food = "pasta mista, peperini,

capellini tagliati,

orzi piccoli, stelline.";

# Rakudo では未実装っぽい

if $food ~~ / @str / {

say "ok";

}

83

6. クロージャ

どこでもコード実行 {code}

Perl 5 Perl 6

/pat(?{code})tern/ # 埋め込みコード

/pat(??{retcode})tern/ # 動的正規表現

/pat{code}tern/

/pat<{retcode}>tern/

my $text = "pattern";

$text =~ m/pat(?{print "ok¥n"})tern/;

if ($text =~ m/pat(??{lc("TER")})n/) {

print "ok¥n";

}

my $text = "pattern";

$text ~~ m/pat{say "ok"}tern/;

if $text ~~ m/pat<{lc("TER")}>n/ {

say "ok";

}

どこでもクロージャ{...}

マッチ失敗 {fail}

Perl 5 Perl 6

/ (...) {fail} /

my $x = qr/(25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])/;

for (0..255) {

/^($x)$/;

}

my $addr = "192.168.1.33";

if ($addr =~ /^($x¥.$x¥.$x¥.$x)$/) {

print "ok¥n";

}

my $x = / (¥d+) {fail if $0 > 255} /;my $ipv4 = /^ $x ¥. $x ¥. $x ¥. $x $/;my $addr = "192.168.1.33";if $addr ~~ /$ipv4/ {

say "ok";}

正規表現のクロージャ内で fail を呼ぶと〃現在のキャプチャ内のマッチに失敗させることができる。これを応用すると、正規表現中に複雑な計算式やプログラムを組み込んでパターンマッチさせられる。

【例】 IPアドレスをチェックする正規表現

[これは便利]

86

7. ルール

正規表現のラブラリ化

Perl 6 Rules & Grammars

grammar Inventory {

regex product { ¥d+ }

regex quantity { ¥d+ }

regex color { ¥S+ }

regex description { ¥N* }

regex TOP { ^^ <product> ¥s+ <quantity> ¥s+

[

| <description> ¥s+ '(' ¥s* <color> ¥s* ')'

| <color> ¥s+ <description>

]

$$

}

Inventory.parse($source_lines);

Example

Target strings Perl 6 code# lib/MyProject/Test.pm

package MyProject::Test;use Test::Base -Base;use MyProject;…package MyProject::Test::Filter;use Test::Base::Filter -base;sub my_filter {

return MyProject->do_something(shift);}

# t/sample.tuse MyProject::Test;

plan tests => 1 * blocks;

run_is input => 'expected';

sub local_filter {s/my/your/;

}

__END__

=== Test one (the name of the test)--- input my_filter local_filtermyinputlines--- expectedexpectedoutput=== Test twoThis is an optional descriptionof this particular test.--- input my_filterotherinputlines--- expectedother expectedoutput

grammar Test::Base::Spec {

rule spec { <block>* }

rule block {<head><comment><section>*

}

rule head {<block_delim> [ <sp>+ <name> ]? ¥n

}

rule comment {[ <!section_delim> <line> ]*

}

rule section {<section_delim><sp>+ <name><sp>+ [ <filter> <sp>+ ]*[ ':' <data> ¥n | ¥n <chunk> ]

}

rule block_delim { ¥=¥=¥= }rule section_delim { ¥-¥-¥- }

rule line { ¥N* ¥n }rule name { ¥N* }rule data { ¥N* }rule filter { ¥S+ }

rule chunk {[ <!block_delim> <!section_delim> <line> ]*

}

}

http://search.cpan.org/~ingy/Test-Base/lib/Test/Base.pm

89

Named capture など

まだまだ紹介しきれない

便利な機能がいっぱい!

90

さらに詳しく

参考URL

Perl 6 rules - Wikipedia http://en.wikipedia.org/wiki/Perl_6_rules

perl6: Apocalypse 5: Pattern Matching (Larry Wall)

http://dev.perl.org/perl6/doc/design/apo/A05.html

perl6: Synopsis 5: Regexes and Rules (Damian Conway)

http://dev.perl.org/perl6/doc/design/syn/S05.html

Perl 6 FAQ - Regexes and Grammars http://www.programmersheaven.com/2/Perl6-FAQ-Regex

Perl6::Rules - Implements (most of) the Perl 6 regex syntax http://search.cpan.org/~dconway/Perl6-Rules/Rules.pm

日本語 Perl6 Rules(新たな正規表現)

http://www9.ocn.ne.jp/~ymt/perl6/rules.html

92

Have fun!

Enjoy Perl 6

Perl 6 正規表現プログラミング楽土入門

top related