正規

正規表現 の Elixir

24個の演習

正規表現について

正規表現(regex)は、Elixirで文字列を扱うための強力なツールです。Elixirの正規表現は、PCRE仕様(Perl Compatible Regular Expressions)に従います。正規表現の意味を表す文字列パターンは、まずコンパイルされ、その後、文字列全体または一部のマッチングに使われます。

Elixirで正規表現を作る最も一般的な方法は、~rシジルを使うことです。シジルは、Elixirでよくあるタスクを_糖衣構文_で短く書けるようにしてくれるものです。この場合、~rはRegex.compile!/2を使うためのショートカットです。

Regex.compile!("test") == ~r/test/
# => true

=~/2演算子を使うと、文字列に対して正規表現マッチを行い、booleanの結果を返せます。

"this is a test" =~ ~r/test/
# => true

正規表現の構文のおさらい

  • 正規表現パターンの中には特別な意味を持つ文字があり、その文字をそのまま使うには\でエスケープする必要があります。例えば~r/\?/のように書きます。
  • 文字クラス(例:\d、\w)を使うと、ある範囲の文字にマッチさせられます
  • 選択(|)を使うと、複数のパターンのいずれかにマッチさせられます
  • 量指定子({N, M}、*、?)を使うと、繰り返すパターンの回数を指定してマッチさせられます
  • グループ(())を使うと、パターンの一部をひとつの単位として扱えます

キャプチャ

正規表現は、文字列の一部を取り出すのにも便利です。これを_キャプチャ_と呼びます。文字列の一部を_キャプチャ_するには、キャプチャしたい部分のグループ(())を作り、Regex.runを使います。

Regex.run(~r/Weight: (\d*)g/, "Weight: 150g")
# => ["Weight: 150g", "150"]

キャプチャには番号が付き(1から始まります)、正規表現で文字列の一部を置き換えるときの結果の中でも使えます。

Regex.replace(~r/Weight: (\d*)g/, "Weight: 150g", "Gewicht: \\1g")
# => "Gewicht: 150g"

キャプチャには、開き括弧のあとに?<name>を付けて名前を付けることもできます。Regex.named_captures/3を使うと、名前付きキャプチャを持つマップを取得できます。

Regex.named_captures(~r/Weight: (?<weight>\d*)g/, "Weight: 150g")
# => %{"weight" => "150"}

修飾子

正規表現の動作は、正規表現の末尾に特別なフラグを付けることで変更できます。例えば~r/test/iのように書きます。

  • caseless i - 大文字と小文字を区別しません
    "A" =~ ~r/a/
    # => false
    "A" =~ ~r/a/i
    # => true
    
  • unicode u - \pのようなUnicode固有のパターンを有効にし、\wなどの文字クラスがUnicodeにもマッチするようにします
    "ö" =~ ~r/^\w$/
    # => false
    "ö" =~ ~r/^\w$/u
    # => true
    
  • その他:dotall、multiline、extended、firstline、ungreedy

正規表現を動的に組み立てる

~rシジルは"pattern" |> Regex.escape() |> Regex.compile!()のショートカットなので、文字列補間を使って正規表現パターンを動的に組み立てることもできます。

anchor = "$"
regex = ~r/end of the line#{anchor}/
"end of the line?" =~ regex
# => false
"end of the line" =~ regex
# => true

正規表現とStringモジュール

正規表現は強力ですが、常に使うのが賢明とは限りません。

  • 使う前にコンパイルが必要で、計算時間とメモリを消費します。
  • 普通の文字列関数を使うよりも遅くなることがあります。

目安として、できるだけStringモジュールの関数を使うほうがよいでしょう。

# Don't use regular expressions to check a suffix:
if "YELLING!" =~ ~r/!$/, do: "Whoa, chill out!"

# Use a string function:
if String.ends_with?("YELLING!", "!"), do: "Whoa, chill out!"
GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

正規表現を学習する

練習はロックされています

正規表現を練習するには、あと10個の演習のロックを解除してください