string/binary 参数末尾的模式匹配

Pattern match on end of a string/binary argument

我目前正在用 Elixir 编写一个小测试运行程序。我想使用模式匹配来评估文件是否为规范格式(以“_spec.exs”结尾)。有很多关于如何在字符串开头进行模式匹配的教程,但不知何故不适用于字符串结尾:

defp filter_spec(file <> "_spec.exs") do
  run_spec(file)
end

defp run_spec(file) do
  ...
end

这总是以编译错误结束:

== Compilation error on file lib/monitor.ex ==
** (CompileError) lib/monitor.ex:13: a binary field without size is only allowed at the end of a binary pattern
    (stdlib) lists.erl:1337: :lists.foreach/2
    (stdlib) erl_eval.erl:669: :erl_eval.do_apply/6

有解决办法吗?

看Elixir入门指南中的这个link,好像是不可能的。相关部分指出:

However, we can match on the rest of the binary modifier:

iex> <<0, 1, x :: binary>> = <<0, 1, 2, 3>>
<<0, 1, 2, 3>>
iex> x
<<2, 3>>

The pattern above only works if the binary is at the end of <<>>. Similar results can be achieved with the string concatenation operator <>

iex> "he" <> rest = "hello"
"hello"
iex> rest
"llo"

由于字符串是 Elixir 中的二进制文件,因此匹配后缀对它们来说也是不可能的。

正如其他答案所提到的,这在 elixir/erlang 中是不可能的。然而,另一种解决方案是使用 Path 模块来解决问题,因此对于您的用例,您应该能够执行以下操作:

dir_path
  |> Path.join( "**/*_spec.exs" )
  |> Path.wildcard

使用更传统的 "pattern match" 定义:

String.match?(filename, ~r"_spec\.exs$")

检查匹配项:

String.ends_with? filename, "_spec.exs"

提取文件:

file = String.trim_trailing filename, "_spec.exs"

如果您预先计算了要匹配的二进制文件的长度,则可以在末尾进行匹配。像这样:

    file = "..."
    postfix = "_spec.exs"
    skip_chars = byte_size(file) - bytes_size(postfix)
    <<_ :: binary-size(skip_chars), post :: little-16>> = file

你可以把它放在一个函数中,但我猜不能放在模式匹配子句中。我相信您也可以很容易地将其扩展为使用 utf8 而不是二进制文件