在Clojure中转义括号

pis*_*hio 5 regex string clojure

如果我试试这个

(import java.util.regex.Pattern)
(Pattern/compile ")!@#$%^&*()")
Run Code Online (Sandbox Code Playgroud)

或这个

(def p #")!@#$%^&*()")
Run Code Online (Sandbox Code Playgroud)

我有Clojure抱怨说有一个无与伦比的/未闭合的).为什么在这个简单的字符串中评估括号?怎么逃避他们?谢谢

编辑:虽然转义在特定于clojure的语法(#"")中工作,但它不能用Pattern/compile我需要的语法,因为我必须从字符串动态编译正则表达式模式.

我试过了re-pattern,但由于某种原因我无法正常逃脱:

(re-pattern "\)!@#$%^&*\(\)")
    java.lang.Exception: Unsupported escape character: \)
    java.lang.Exception: Unable to resolve symbol: ! in this context (NO_SOURCE_FILE:0)
    java.lang.Exception: No dispatch macro for: $
    java.lang.Exception: Unable to resolve symbol: % in this context (NO_SOURCE_FILE:0)
    java.lang.IllegalArgumentException: Metadata can only be applied to IMetas
Run Code Online (Sandbox Code Playgroud)

编辑2这个小功能可能会有所帮助:

(defn escape-all [x]
    (str "\\" (reduce #(str  %1 "\\" %2) x)))
Run Code Online (Sandbox Code Playgroud)

Omr*_*ein 10

我通过双重逃避一切来实现它.哦,双重逃避的乐趣.

=> (re-pattern "\\)\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)")
=> #"\)\!\@\#\$\%\^\&\*\(\)"

=> (re-find (re-pattern "\\)\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)")
            ")!@#$%^&*()")
=> ")!@#$%^&*()"
Run Code Online (Sandbox Code Playgroud)

我建议编写一个辅助函数str-to-pattern(或任何你想要的函数),它接受一个字符串,双重转义所需的一切,然后调用re-pattern它.

编辑:使字符串模式化功能
有很多方法可以做到这一点,下面只是一个例子.我首先将正则表达式转义为字符串替换."smap"不是实际类型,但从功能上来说,它是我们用来将"旧值"与"新值"交换的地图,其中"旧值"是smap键的成员,以及"新值"是相应的smap的成员.在我们的例子中,这个smap看起来像{\( "\\(", \) "\\)" ...}.

(def regex-char-esc-smap
  (let [esc-chars "()*&^%$#!"]
    (zipmap esc-chars
            (map #(str "\\" %) esc-chars))))
Run Code Online (Sandbox Code Playgroud)

接下来是实际功能.我使用上面的smap替换传递给它的字符串中的项目,然后将其转换回字符串并从中生成正则表达式模式.我认为->>宏使代码更具可读性,但这只是个人偏好.

(defn str-to-pattern
  [string]
  (->> string
       (replace regex-char-esc-smap)
       (reduce str)
       re-pattern))
Run Code Online (Sandbox Code Playgroud)