LoginSignup
16
8

More than 5 years have passed since last update.

Elixirで正規表現

Posted at

Elixirでは正規表現を使用する際に、Regexモジュールを使用します。

Document

RegexはPCRE(Perl Compatible Regular Expressions) に基いています。

正規表現は ~r/pattern/ で扱われます。

optionの説明はDocumentにまかせて、
各種ファンクションを使ってみようと思います。

実行しているversionは1.2.0です。

compile(source, options \ "")

sourceにはbinaryを指定します。
Elixirでbinaryとは""で囲った文字列のことです。

iex(3)> Regex.compile("AbC")
{:ok, ~r/AbC/}

iex(4)> {:ok, pattern} = Regex.compile("AbC")
{:ok, ~r/AbC/}

iex(8)> {:ok, pattern} = Regex.compile("AbC", [:unicode])
{:ok, ~r/AbC/}
```

optionsはatomの配列を渡します。
optionsの一覧はこれです。

compile!(source, options \ "")

こちらはエラー時に、Regex.CompileErrorというExceptionを吐いて失敗します。

escape(string)

compile時はsourceといっていたのにこちらはstring
同じだと思うけど、違うのだろうか・・。

iex(15)> Regex.escape("Ab.C")
"Ab\\.C"

文字列を渡した際にエスケープ対象の文字列があったらエスケープされます。

match?(regex, string)

正規表現にマッチしているかを判定します。

compileで作成したpatternか、~rのsigilでパターンでregexを指定します。

iex(16)> Regex.match?(pattern, "AbC")
true

iex(17)> Regex.match?(~r/AbC/, "AbC")
true

named_captures(regex, string, options \ [])

正規表現にマッチした名前付きキャプチャをマップで返します。

optionsに、%{ return: :index }を渡すことで、戻り値を文字列ではなく、
stringのindexで返すこともできます。

iex(19)> Regex.named_captures(~r/A(?<hoge>b)C/, "AbC")
%{"hoge" => "b"}

iex(20)> Regex.named_captures(~r/A(?<hoge>b)C/, "AbC", [return: :index])
%{"hoge" => {1, 1}}

names(regex)

Regex中の名前付きキャプチャの名前を返します。

iex(21)> Regex.names(~r/A(?<hoge>b)C/)
["hoge"]

opts(regex)

Regexのoptionを返します。

iex(24)> Regex.opts(~r/A(?<hoge>b)C/mi)
"mi"

re_pattern(regex)

re_patternを返します。

iex(26)> Regex.re_pattern(~r/AbC/)
{:re_pattern, 0, 0, 0,
 <<69, 82, 67, 80, 69, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 65, 0, 67, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>}

re_patternはおそらく erlangの :re モジュールで使用する regex のことですね。

:reモジュールのcompileファンクションを使用すると同じ結果が得られます。

iex(27)> :re.compile("AbC")
{:ok,
 {:re_pattern, 0, 0, 0,
  <<69, 82, 67, 80, 69, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 65, 0, 67, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>}}

regex?(term)

与えられた引数がRegexパターンかどうかを判定します。

iex(28)> Regex.regex?(~r/Abc/)
true

replace(regex, string, replacement, options \ [])

stringからregexにマッチした部分をreplacementに置き換えます。

iex(29)> Regex.replace(~r/Abc/, "Abc", "ABC")
"ABC"

## デフォルトではマッチが複数あった場合に全て置き換えます。
iex(30)> Regex.replace(~r/Abc/, "AbcTAbc", "ABC")
"ABCTABC"

## globalオプションにfalseを渡すことで1つめのマッチのみを置き換えられます。
iex(33)> Regex.replace(~r/Abc/, "AbcTAbc", "ABC", global: false)
"ABCTAbc"

## \\1 はマッチしたキャプチャ部分が取得できます。
iex(34)> Regex.replace(~r/a(b|d)c/, "abcadc", "[\\1]")
"[b][d]"

## \\0 はマッチ全体になります。
iex(35)> Regex.replace(~r/a(b|d)c/, "abcadc", "[\\0]")
"[abc][adc]"

## キャプチャと文字列を組み合わせる場合は \\g{N} を使用します。
iex(40)> Regex.replace(~r/\.(\d)$/, "500.5", ".\\g{1}0")
"500.50"

## replacementは関数を指定することもできます。
iex(41)> Regex.replace(~r/a(b|d)c/, "abcadc", fn _, x -> "[#{x}]" end)
"[b][d]"

## 第一引数には、マッチ全体が与えられます。
iex(42)> Regex.replace(~r/a(b|d)c/, "abcadc", fn all, x -> "[#{all}]" end)
"[abc][adc]"

run(regex, string, options \ [])

最初にマッチする文字列があるまでマッチを続けます。
マッチしなかった場合は nil を返します。

iex(43)> Regex.run(~r/Abc/, "AbcAbc")
["Abc"]
iex(44)> Regex.run(~r/Abc/, "AbC")
nil

# キャプチャがある場合はそれも返ります。
iex(46)> Regex.run(~r/A(b)c/, "Abc")
["Abc", "b"]

# returnオプションにindexを指定すると、indexで返却されます。
iex(47)> Regex.run(~r/A(b)c/, "Abc", [return: :index])
[{0, 3}, {1, 1}]

scan(regex, string, options \ [])

全てのマッチを集める、runというイメージです。

iex(49)> Regex.scan(~r/c(d|e)/, "abcd abce")
[["cd", "d"], ["ce", "e"]]

source(regex)

compileファンクションの逆。
regexをバイナリにします。

iex(50)> Regex.source(~r/AbC/)
"AbC"

split(regex, string, options \ [])

stringをregexのパターンで分割します。

iex(51)> Regex.split(~r/-/, "a-b-c")
["a", "b", "c"]

## partsオプションを指定すると、指定した数に分割します。
iex(52)> Regex.split(~r/-/, "a-b-c", [parts: 2])
["a", "b-c"]

## trimオプションを指定すると、結果から、空文字列を除く。らしいがうまくいってない。
iex(54)> Regex.split(~r/-/, "a- b- c", trim: true)
["a", " b", " c"]

## キャプチャを分割パターンにする。
iex(58)> Regex.split(~r/a(?<hoge>b)c/, "abc", on: [:hoge])
["a", "c"]

おわり

16
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
8