如何在Erlang中将通配符模式转换为正则表达式?

时间:2013-06-13 01:18:47

标签: erlang

通配符模式是文件系统标准,它将任何字符与(?)匹配,任何序列字符与(*)匹配。

我正在尝试使用erlang re:replace/3函数替换:

a)*加入.*

b)?进入.

c).进入\.

d)如果通配符模式没有在通配符中启动,则在模式的末尾添加^(正则表达式中的起始匹配)

e)如果通配符模式不以通配符结尾,则在模式的末尾添加$(正则表达式中的结束匹配)

不知怎的,我无法得到re:replace来实现这个目标。

示例:

尝试根据上面的项目a)替换

re:replace("something*.log","\*","\.\*").
exception error: bad argument

2 个答案:

答案 0 :(得分:1)

如果您对规范的完整性有信心,可以直接编写转换(我猜没有性能问题,因为正则表达式通常是短列表)

-module(rep).
-compile([export_all]).

replace(L) when is_list(L) -> lists:reverse(replace(L,wildcard(hd(L)))).

% take care of the first character
replace(L,W={true,_}) -> replace(L,W,[]);
replace(L,W={false,_}) -> replace(L,W,[$^]).

% take care of the last character
replace([_],{true,R},Res) -> R ++ Res;
replace([_],{false,R},Res) -> [$$|R] ++ Res;
% middle characters
replace([_|Q],{_,R},Res) -> replace(Q,wildcard(hd(Q)),R++Res).

wildcard($*) -> {true,[$*,$.]};
wildcard($?) -> {true,[$.]};
wildcard($.) -> {true,[$.,$\\]};
wildcard(C) -> {false,[C]}.

以你的例子:

11> rep:replace("something*.log").
"^something.*\\.log$"

请注意,\\是一个单个字符,您可以通过以下方式进行验证:

12> length(rep:replace("something*.log")).
18

答案 1 :(得分:0)

re:replace来电:

re:replace("something*.log","\*","\.\*").

反斜杠实际上并没有在字符串中结束,因为它们只是逃避了以下字符。一些反斜杠转义具有特殊含义,例如"\n"表示换行符,但不会让角色保持不变:

4> "\*".
"*"

所以你需要一个反斜杠的双反斜杠来实际上成为字符串的一部分:

5> re:replace("something*.log","\\*","\.\*").
[<<"something">>,<<".*">>|<<".log">>]

请注意,不需要"\.\*"中的反斜杠。

上面的返回值是一个iolist,它通常非常有用(特别是如果你想将结果写入文件或套接字),但有时你可能需要一个额外内存和CPU成本的普通字符串。您可以将第四个参数传递给re:replace

7> re:replace("something*.log","\\*","\.\*", [{return, list}]).   
"something.*.log"