TL; DR:
25> re:run("йцу.asd", xmerl_regexp:sh_to_awk("*.*"), [{capture, none}]).
** exception error: bad argument
in function re:run/3
called as re:run([1081,1094,1091,46,97,115,100],
"^(.*\\..*)$",
[{capture,none}])
如何使这项工作?显然,'йцу'是不属于拉丁字符集的字符;有没有办法告诉re模块或整个系统使用不同的“字符串”字符集运行?
原始问题(记录):
另一个“编程Erlang”问题)
在第16章中有一个关于从mp3文件中读取标签的例子。它很有效。但是,在提供的模块 lib_find 中似乎存在一些错误,该模块具有搜索路径以匹配文件的功能。这是有效的电话:
61> lib_find:files("../..", "*.mp3", true).
["../../early/files/Veronique.mp3"]
并且此调用失败:
62> lib_find:files("../../..", "*.mp3", true).
** exception error: bad argument
in function re:run/3
called as re:run([46,46,47,46,46,47,46,46,47,46,107,101,114,108,47,98,117,
105,108,100,115,47,50,48,46,49,47,111|...],
"^(.*\\.mp3)$",
[{capture,none}])
in call from lib_find:find_files/6 (lib_find.erl, line 29)
in call from lib_find:find_files/6 (lib_find.erl, line 39)
in call from lib_find:files/3 (lib_find.erl, line 17)
具有讽刺意味的是,调查导致在Erlang自己的安装中找到了罪魁祸首:
.kerl /建立/ 20.1 / otp_src_20.1 / LIB / SSH /测试/ ssh_sftp_SUITE_data / sftp_tar_test_data_高兴
好吧,这似乎意味着Erlang正在使用更严格的默认字符集,其中不包括hànzì。有什么选择?显然,我可以忽略这一点并继续我的学习,但我觉得我可以从这一个中学到更多东西=)例如 - 我在哪里/如何修复默认的字符集?我有点惊讶它默认是UTF8以外的东西 - 所以也许我的轨道错了?
谢谢!
答案 0 :(得分:3)
<强> TL; DR:强>
通过使用选项unicode
将正则表达式模式置于unicode模式,可以访问UTF-8正则表达式。 (请注意,字符串"^(.*\\..*)$"
是您调用xmerl_regexp:sh_to_awk/1
的结果。)
1> re:run("なにこれ.txt", "^(.*\\..*)$").
** exception error: bad argument
in function re:run/2
called as re:run([12394,12395,12371,12428,46,116,120,116],"^(.*\\..*)$")
2> re:run("なにこれ.txt", "^(.*\\..*)$", [unicode]).
{match,[{0,16},{0,16}]}
从您的确切示例:
11> re:run("йцу.asd", "^(.*\\..*)$", [unicode, {capture, none}]).
match
或者
12> {ok, Pattern} = re:compile("^(.*\\..*)$", [unicode]).
{ok,{re_pattern,1,1,0,
<<69,82,67,80,87,0,0,0,16,8,0,0,65,0,0,0,255,255,255,
255,255,255,...>>}}
13> re:run("йцу.asd", Pattern, [{capture, none}]).
match
re
的文档非常冗长,但这是因为正则表达式本身就是一个复杂的主题。您可以在re:compile/2
的文档中找到已编译的正则表达式的选项,以及在re:run/3
的文档中运行的选项。
<强>讨论强>
Erlang已经确定了字符串虽然仍然是代码点列表,但都是UTF-8 everywhere。当我在日本工作并且一直处理这个问题时,这对我来说是一个很大的缓解,因为我可以停止使用我过去需要的大约一半的转换库(yay!),但是有点复杂的事情对于string
模块的用户,因为many operations there now perform under slightly different assumptions(字符串仍然被认为是“平坦的”,即使它是字形集群的深层列表,只要这些集群存在于列表的第一级)
不幸的是,编码并不是一件容易处理的事情,一旦你走出最常见的表现形式,UTF-8就不那么简单 - 这是一项正在进行的工作。不过,我可以放心地告诉你,处理二进制,字符串,深层列表和io_data()
表单中的UTF-8数据,无论是文件名,文件数据,网络数据,还是来自WX或Web表单的用户输入一旦你阅读了unicode,正则表达式和字符串文档,就会按预期工作。
但那当然是很多熟悉的东西。如果您使用unicode:characters_to_list/1
和unicode:characters_to_binary/1
将所有来自外部的内容解码为UTF-8,并且将二进制字符串指定为utf8
binary types,那么99%的时间会按预期工作:
3> UnicodeBin = <<"この文書はUTF-8です。"/utf8>>.
<<227,129,147,227,129,174,230,150,135,230,155,184,227,129,
175,85,84,70,45,56,227,129,167,227,129,153,227,128,130>>
4> UnicodeString = unicode:characters_to_list(UnicodeBin).
[12371,12398,25991,26360,12399,85,84,70,45,56,12391,12377,
12290]
5> io:format("~ts~n", [UnicodeString]).
この文書はUTF-8です。
ok
6> re:run(UnicodeString, "UTF-8", [unicode]).
{match,[{15,5}]}
7> re:run(UnicodeBin, "UTF-8", [unicode]).
{match,[{15,5}]}
8> unicode:characters_to_binary(UnicodeString).
<<227,129,147,227,129,174,230,150,135,230,155,184,227,129,
175,85,84,70,45,56,227,129,167,227,129,153,227,128,130>>
9> unicode:characters_to_binary(UnicodeBin).
<<227,129,147,227,129,174,230,150,135,230,155,184,227,129,
175,85,84,70,45,56,227,129,167,227,129,153,227,128,130>>