二进制类型上的模式匹配不能使用变量的值

Hen*_*_Cl 5 erlang elixir

例如:

arg = "echo:hello"
prefix = "echo"

case arg do
  <<^prefix, ":", msg::binary>> -> IO.puts("Echo message: #{msg}")
  _ -> IO.puts("No match")
end
Run Code Online (Sandbox Code Playgroud)

结果: No match

如果我想使用prefix模式匹配的值,该怎么办?

Jon*_*ger 8

这不起作用,因为如果您不匹配字符串的"其余",则只能匹配固定大小的二进制文件.根据您的使用情况,有3种不同的解决方案

1.事先计算尺寸

如果您确实想使用二进制模式匹配,可以事先手动计算大小:

arg = "echo:hello"
prefix = "echo"
prefix_size = byte_size(prefix)

case arg do
  <<^prefix::binary-size(prefix_size), ":", msg::binary>> -> IO.puts("Echo message: #{msg}")
  _ -> IO.puts("No match")
end
Run Code Online (Sandbox Code Playgroud)

2.使用编译时模块属性

根据您的使用情况,您可以使用模块属性,这些属性在编译时已知,因此它们可以正常工作:

defmodule MyModule do

  @prefix "echo"

  def test(arg) do
    case arg do
      <<@prefix::binary, ":", msg::binary>> -> IO.puts("Echo message: #{msg}")
      _ -> IO.puts("No match")
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

3.使用String.replace_prefix/3

或者,如果要保留prefix运行时二进制文件,可以使用String.replace_prefix/3

arg = "echo:hello"
prefix = "echo"

case String.replace_prefix(arg, "#{prefix}:", "")do
  ^arg -> IO.puts("No match")
  msg -> IO.puts("Echo match: #{msg}") 
end
Run Code Online (Sandbox Code Playgroud)

String.replace_prefix/3如果找不到匹配项,则返回输入字符串,因此我们通过匹配它^arg.如果不是这种情况,我们得到一个匹配,因为我们用前缀替换了前缀"",我们只是得到了后面的部分:.