在Ocaml中拆分字符串 - 但不是在使用反斜杠转义分隔符时

时间:2012-12-16 01:44:12

标签: regex split escaping ocaml

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

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

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

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

这太简单了,我需要通过在反斜杠前面加上字符串来逃避。

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

有什么想法吗?

我应该提一下,我注意到Ocaml-parser会自动转义字符串中的反斜杠,所以字符串就像: "foobar\/barfoo"已转换为"foobar\\/barfoo"。所以也许实际上想要删除字符串中所有偶数反斜杠。

3 个答案:

答案 0 :(得分:3)

你需要两次逃避反斜杠:

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

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

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

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

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

如果'/'中的"\\/"有一个很好的替换字符,那么最后一个可能是最快的。

答案 1 :(得分: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"]

虽然有点过于神秘,但仍然可以完成这项任务。

希望这有帮助!

答案 2 :(得分: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"]

如果您想摆脱\/字符串转义,您将需要后处理拆分的结果或(更好)使用匹配和建立自己的列表。