【问题标题】:String.replace returning binary representation of stringString.replace 返回字符串的二进制表示
【发布时间】:2014-10-31 04:27:32
【问题描述】:

我正在学习灵药,遇到了一些对我来说没有意义的东西......

我正在尝试删除标点符号

"Freude schöner Götterfunken" |> String.replace(~r/[^\s\w]/, "") #=> <<70, 114, 101, 117, 100, 101, 32, 115, 99, 104, 195, 110, 101, 114, 32, 71, 195, 116, 116, 101, 114, 102, 117, 110, 107, 101, 110>>
"Freude schöner Götterfunken" |> String.replace(~r/[^\w]/, "") #=> <<70, 114, 101, 117, 100, 101, 32, 115, 99, 104, 195, 110, 101, 114, 32, 71, 195, 116, 116, 101, 114, 102, 117, 110, 107, 101, 110>>
"Freude schöner Götterfunken" |> String.replace(~r/\p{P}/, "") #=> <<70, 114, 101, 117, 100, 101, 32, 115, 99, 104, 195, 110, 101, 114, 32, 71, 195, 116, 116, 101, 114, 102, 117, 110, 107, 101, 110>>
"Freude schöner Götterfunken" |> String.replace(~r/\s/, "") #=> FreudeschönerGötterfunken
"Hi my name is bob" |> String.replace(~r/\w/, "") #=> "    "
Regex.run(~r/[^\w]/, "Freude schöner Götterfunken") #=> [<<182>>]

这似乎是一个错误,但作为一个菜鸟,我假设我是无知的。为什么替换不返回字符串?

【问题讨论】:

    标签: elixir


    【解决方案1】:

    你说得对,String.replace/2 没有返回字符串,因为 Elixir 将字符串定义为 utf-8 编码的二进制文件。但是,这不是错误,因为 Elixir 期望您传递或对参数执行有效操作,因为它不会验证所有结果(因为成本很高)。

    例如,如果您将上面的任何二进制文件传递给String.downcase/1,Elixir 会将它知道的部分小写,而忽略其余部分。它起作用的原因是因为 UTF-8 自动同步,所以如果我们看到一些奇怪的东西,我们可以跳过奇怪的字节并继续执行操作。

    换句话说,Elixir 中字符串处理的理念是在边界处进行验证(例如在打开文件、执行 I/O 或从数据库读取时),并假设我们自始至终都在处理和执行有效操作。

    好吧,说了这么多,为什么你的代码不起作用?原因是您的正则表达式没有启用 unicode。让我们添加 u 修饰符:

    iex> "Freude schöner Götterfunken" |> String.replace(~r/[^\s\w]/u, "")
    "Freude schöner Götterfunken"
    

    好吧,它并不能解决您的问题,但至少结果是有效的。 Reading about unicode categories here 意味着我们无法用 unicode 属性真正解决这个问题,因为您的示例中的 ö 是与 \p{L} 属性匹配的单个代码点。

    在这种情况下,假设您只想解决德语问题,也许最简单的解决方案就是遍历二进制文件,保持字节

    iex> for <<x <- "Freude schöner Götterfunken">>, x <= 127, into: "", do: <<x>>
    "Freude schner Gtterfunken"
    

    如果您想要更完整的解决方案,您可能应该研究 unicode 音译。

    【讨论】:

    • 很棒的答案!谢谢你的详细解释。我在阅读文档时错过了 u 修饰符。
    【解决方案2】:

    String.replace 返回一个“字符串”,但双引号字符串实际上存储为 Elixir 中的二进制文件。由于某种原因,输出无法显示为常规字符串,因此,它回退到显示二进制表示。

    【讨论】:

    • “出于某种原因”在这里:elixir-lang.org/getting_started/6.html#6.3-char-lists。请注意以下句子:“(请注意,如果任何字符超出 ASCII 范围,iex 只会输出代码点)。”由于@matmer 的字符超出了 ASCII 范围,因此整个内容显示为代码点。
    猜你喜欢
    • 2016-09-21
    • 2017-09-28
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    • 2023-03-18
    • 2019-12-04
    • 2011-08-03
    • 2023-03-02
    相关资源
    最近更新 更多