【问题标题】:Split string in Ocaml - but not when delimiter is escaped by backslash在 Ocaml 中拆分字符串 - 但不是当分隔符被反斜杠转义时
【发布时间】:2012-12-16 01:44:11
【问题描述】:

目标:能够拆分以下字符串:"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"。所以也许有人真的想删除字符串中的所有偶数反斜杠。

【问题讨论】:

    标签: regex split escaping ocaml


    【解决方案1】:

    你需要两次转义反斜杠:

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      希望这会有所帮助!

      【讨论】:

        【解决方案3】:

        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-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-09
          • 2022-12-19
          • 2020-05-06
          • 1970-01-01
          • 2011-09-08
          相关资源
          最近更新 更多