<>
を使用すればシンプルなpattern-matchで実現可能
iex> origin
"2018-07-05T12-2"
iex> "2018-07-05T" <> aft = origin
"2018-07-05T12-2"
iex> aft
"12-2"
末尾文字以外は<>
を使用したpattern-matchは行えない。
iex> origin
"2018-07-05T12-2"
iex> yyyymmdd<>"T"<>aft = origin
** (CompileError) iex:16: a binary field without size is only allowed at the end of a binary pattern
こういうケースは<< >>
を使用したbinary-pattern-matchを行える
iex> origin = "2018-07-05T12-2"
"2018-07-05T12-2"
iex> <<yyyymmdd::bytes-size(10)>> <> "T" <> aft = origin
"2018-07-05T12-2"
# yyyymmdd変数に、byes-size=10(桁)分をpattern-match
iex> yyyymmdd
"2018-07-05"
iex> aft
"12-2"
ただし、この記述だと文字列のlengthが事前にわかっている必要がある。
例えば、上記の「aft変数にpattern-matchされた値の12
が、zero-paddingされない時間
」の場合、その時間が0
〜9
の時は1桁になってしまう。
こういうケースは「関数によるpattern-match」や「case文によるpattern-match」などで処理を分岐させる必要がある
iex> func = fn
...> <<yyyymmdd::bytes-size(10)>> <> "T" <> <<h::bytes-size(1)>> <> "-" <> <<mm::bytes-size(1)>> -> [yyyymmdd, h, mm]
...> <<yyyymmdd::bytes-size(10)>> <> "T" <> <<h::bytes-size(2)>> <> "-" <> <<mm::bytes-size(1)>> -> [yyyymmdd, h, mm]
...> end
#Function<6.99386804/1 in :erl_eval.expr/5>
iex> data12 = "2018-07-05T12-2"
"2018-07-05T12-2"
iex> data3 = "2018-07-05T3-2"
"2018-07-05T3-2"
iex> func.(data12)
["2018-07-05", "12", "2"]
iex> func.(data3)
["2018-07-05", "3", "2"]
iex> case data12 do
...> <<yyyymmdd::bytes-size(10)>> <> "T" <> <<h::bytes-size(1)>> <> "-" <> <<mm::bytes-size(1)>> -> [yyyymmdd, h, mm]
...> <<yyyymmdd::bytes-size(10)>> <> "T" <> <<h::bytes-size(2)>> <> "-" <> <<mm::bytes-size(1)>> -> [yyyymmdd, h, mm]
...> end
["2018-07-05", "12", "2"]
iex> defmodule M do \
...> def parse(<<yyyymmdd::bytes-size(10)>> <> "T" <> <<h::bytes-size(1)>> <> "-" <> <<mm::bytes-size(1)>>), do: [yyyymmdd, h, mm]
...> def parse(<<yyyymmdd::bytes-size(10)>> <> "T" <> <<h::bytes-size(2)>> <> "-" <> <<mm::bytes-size(1)>>), do: [yyyymmdd, h, mm]
...> end
iex> M.parse(data12)
["2018-07-05", "12", "2"]
iex> M.parse(data3)
["2018-07-05", "3", "2"]
String.split/2
上記ケースだと、どちらにしてもlengthが固定値になり融通が効かなくなるし、見た目もスマートな方法でない。 結局は、素直に文字列を分割してpattern-matchさせたほうがスマートになりそう。
iex> data12 = "2018-07-05T12-2"
"2018-07-05T12-2"
iex> [yyyymmdd, aft] = String.split(data12, "T")
["2018-07-05", "12-2"]
iex> [h, m] = String.split(aft, "-")
["12", "2"]
iex> [yyyymmdd, h, m]
["2018-07-05", "12", "2"]
String.split/2
を使用したほうがスマートになる