3

目标:能够拆分以下字符串:"command/test \/ escaped/"

进入以下列表:["command", "test / escaped"]

当前的正则表达式如下所示:

Str.split (Str.regexp "/") string_to_split;;

这太简单了,我需要在字符串前面加上反斜杠来转义。

我试过这个:Str.regexp "((?!\\).)/"但它不适用于 Ocaml 解析器,产生:uncaught exception Failure("spurious \) in regular expression")

有任何想法吗?

我应该提一下,我注意到 Ocaml 解析器会自动转义字符串中的反斜杠,因此像:这样的字符串 "foobar\/barfoo"会转换为"foobar\\/barfoo". 因此,也许有人实际上想要删除字符串中的所有偶数反斜杠。

4

3 回答 3

3

您需要两次转义反斜杠:

  • 一次用于字符串内容
  • 一次用于正则表达式

所以正确的正则表达式是Str.regexp "((?!\\\\).)/".

但是,该正则表达式不起作用。

我建议改为 3 种其他解决方案:

  • match_beginning使用等手动进行搜索和拆分,
  • 对字符使用简单的拆分'/',并根据需要重新组合字符串,
  • 用另一种组合替换\\/字符,比如说\\§(或其他一些不太可能出现在您希望处理的文本中的字符串),进行拆分,然后在每个子字符串中进行反向替换(这次仅将 '§' 替换为 '/ ')。

如果你有一个很好的 in 替换字符,最后一个可能是最快'/'"\\/"

于 2012-12-16T06:21:56.220 回答
1

这是一个不太明显的解决方案:

let rec split s = Scanf.sscanf s "%s@/%s@\n" (fun left right ->
  let llen = String.length left in
  let (left, escaped) = 
    if llen > 0 && left.[llen - 1] = '\\' then
      (String.sub left 0 (llen - 1), true) 
    else
      (left, false) in
  if right = "" then
    [left]
  else match split right with
    h :: t when escaped ->
      (left ^ "/" ^ h) :: t|
    ht ->
      left :: ht         
);;

和输出:

# split "command/test \\/ escaped/";;
- : string list = ["command"; "test / escaped"]

这有点太神秘了,但仍然可以完成这项工作。

希望这可以帮助!

于 2012-12-16T17:57:31.137 回答
0

AFAIR,Str.regexp不支持!构造。

但是,PCRE-OCaml库会:

# #directory "+pcre";;
# #load "pcre.cma";;
# Pcre.split 
    ~rex:(Pcre.regexp ~flags:[`EXTENDED] "(?<!\\\\)/")
    "command/test \\/ escaped/"
  ;;
- : string list = ["command"; "test \\/ escaped"]

如果你想摆脱\/字符串转义,你要么必须对split的结果进行后处理,要么(更好地)使用match并自己构建该列表。

于 2012-12-17T17:34:15.063 回答