String.replace返回字符串的二进制表示

时间:2014-10-30 05:39:57

标签: elixir

我正在学习灵药,并且遇到了一些对我没有意义的事情......

我试图删除标点符号

"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>>]

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

2 个答案:

答案 0 :(得分:20)

你是对的,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}属性匹配的单个代码点。

在这种情况下,也许最简单的解决方案,假设您只想为德语解决它,就是遍历二进制文件,保持字节数&lt; = 127.如下所示:

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

如果你想要一个更完整的解决方案,你应该考虑unicode音译。

答案 1 :(得分:0)

String.replace正在返回&#34;字符串&#34;但双引号字符串实际上存储为Elixir中的二进制文件。由于某种原因,输出不能显示为常规字符串,因此,它会回退到显示二进制表示。