Elixir方法模式匹配与字符串包含

5

有没有办法在参数匹配中进行字符串包含/正则表达式匹配? 例如,字符串是“发生了一些错误”。但我想匹配子字符串“错误发生了”。我尝试过这个方法,但它不起作用:

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

  end
2个回答

12

不,无论是使用模式匹配还是守卫函数都不能进行字符串包含或正则表达式匹配。最好的方法是在模式中匹配{: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"开头的任何字符串。


0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接