与字符串匹配的Elixir方法模式匹配

时间:2017-06-29 10:43:16

标签: pattern-matching elixir

在参数匹配中是否有任何方法可以使用String contains / regex? 例如,字符串是“发生了一些错误”。但我希望它匹配子串“发生错误”。我尝试了这个,但它不起作用:

  defp status({:error, ~r/error happened/}, state) do

  end

2 个答案:

答案 0 :(得分:6)

不可以使用模式匹配或保护功能来完成String包含和Regex匹配。您最好的选择是匹配模式中的{:error, error}并使用例如函数内的字符串匹配进行匹配。 cond

defp status({:error, error}, state) do
  cond do
    error =~ "error happened" -> ...
    ...
  end
end

模式匹配可以做的是前缀匹配。如果这对您来说足够好,您可以这样做:

defp status({:error, "error happened" <> _}, state) do

这将匹配以"error happened"开头的任何字符串。

答案 1 :(得分:0)

虽然@Dogbert的答案是绝对正确的,但是当错误消息不能超过140个符号(也就是推特大小的错误消息)时,可以使用一种技巧。

defmodule Test do
  @pattern "error happened"
  defp status({:error, @pattern <> _rest }, state),
    do: IO.puts "Matched leading"
  Enum.each(1..140, fn i ->
    defp status({:error, 
                 <<_ :: binary-size(unquote(i)), 
                   unquote(@pattern) :: binary,
                   rest :: binary>>}, state),
      do: IO.puts "Matched"
  end)
  Enum.each(0..140, fn i ->
    defp status({:error, <<_ :: binary-size(unquote(i))>>}, state),
      do: IO.puts "Unmatched"
  end)
  # fallback
  defp status({:error, message}, state) do
    cond do
      message =~ "error happened" -> IO.puts "Matched >140"
      true -> IO.puts "Unatched >140"
    end
  end

  def test_status({:error, message}, state),
    do: status({:error, message}, state)
end

试验:

iex|1 ▶ Test.test_status {:error, "sdf error happened sdfasdf"}, nil
Matched

iex|2 ▶ Test.test_status {:error, "sdf errors happened sdfasdf"}, nil
Unmatched

iex|3 ▶ Test.test_status {:error, "error happened sdfasdf"}, nil     
Matched leading

iex|4 ▶ Test.test_status {:error, 
...|4 ▷    String.duplicate(" ", 141) <> "error happened sdfasdf"}, nil
Matched >140