【问题标题】:Pattern match on end of a string/binary argument字符串/二进制参数末尾的模式匹配
【发布时间】:2019-02-26 16:29:35
【问题描述】:

我目前正在用 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


    【解决方案1】:

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

    但是,我们可以匹配二进制修饰符的其余部分:

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

    仅当二进制文件位于&lt;&lt;&gt;&gt; 的末尾时,上述模式才有效。使用字符串连接运算符&lt;&gt;

    可以实现类似的结果
    iex> "he" <> rest = "hello"
    "hello"
    iex> rest
    "llo"
    

    由于字符串是 Elixir 引擎盖下的二进制文件,因此它们也应该不可能匹配后缀。

    【讨论】:

      【解决方案2】:

      使用更传统的“模式匹配”定义:

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

      【讨论】:

        【解决方案3】:

        检查匹配:

        String.ends_with? filename, "_spec.exs"
        

        解压文件:

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-23
              • 1970-01-01
              • 2019-09-13
              • 2019-12-18
              相关资源
              最近更新 更多