読者です 読者をやめる 読者になる 読者になる

Elixirで正規表現

Elixir の正規表現Regexモジュール を使う。

仕事ではPHPを書くことが多い。PHP正規表現PCRE関数 が標準的だろう。普段使うPCRE関数をElixirのRegex で置き換えるとしたらどうなるのか?

比較の対象は preg-matchpreg_replace の二つにする。理由は、その二つをよく使うので (その二つくらいしか使わないとも言う)。

preg_match と比べて
単純なマッチ

単純にマッチするかどうかを判定する場合, Regex.match?/2 を使う。

<?php
echo preg_match('/foo/', 'foo');
// => 1
iex> Regex.match?(~r/foo/, "foo")
true
名前なしキャプチャ

名前なしキャプチャを利用する場合, Regex.run/3 を使う。preg_match はキャプチャした結果は変数の参照を介して受け取る。Regex の場合 run/3 の返り値として受けとる。

一度マッチしたらそこで処理は打ち切られる。打ち切られたくない場合は Regex.scan/3 を使う (PHP なら preg_match_all)。

<?php
preg_match('/c(d)/', 'abcd', $m);
print_r($m);
// => Array
//    (
//        [0] => cd
//        [1] => d
//    )
iex> Regex.run(~r/c(d)/, "abcd")
["cd", "d"]
名前つきキャプチャ

名前つきキャプチャは Regex.named_captures/3。Regex.named_captures/3 はキャプチャされた部分のみの結果になる。

<?php
preg_match('/c(?<foo>d)/', "abcd", $m);
print_r($m);
// => Array
//    (
//        [0] => cd
//        [foo] => d
//        [1] => d
//    )
iex> Regex.named_captures(~r/c(?<foo>d)/, "abcd")
%{"foo" => "d"}
preg_replace と比べて

Regex.replace で置換を行う。引数の順序が違うので慣れで書くと間違う。

<?php
echo preg_replace('/b/', 'd', 'abc').PHP_EOL;
// => adc

echo preg_replace('/\.(\d)$/', '.${1}0', '500.5');
// => 500.50
iex> Regex.replace(~r/b/, "abc", "d")
"adc"

iex> Regex.replace(~r/\.(\d)$/, "500.5", ".\\g{1}0")
"500.50"

感想

PHP でできていたことは Elixir でもできる(まあ、PCRE互換だし)。

PHPの場合はパラメータによって一つの関数の中で機能をon/offしたりする感じだけれど、Elixir は機能ごとに関数を用意する感じ。