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 而不是二进制文件
我目前正在用 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 而不是二进制文件