If I try this
(import java.util.regex.Pattern)
(Pattern/compile ")!@#$%^&*()")
or this
(def p #")!@#$%^&*()")
I have Clojure complaining that there is an unmatched / unclosed ). Why are brackets evaluated within this simple string? How to escape them? Thanks
EDIT: While escaping works in the clojure-specific syntax (#""), it doesn’t work with the Pattern/compile syntax that I do need because I have to compile the regex patter dynamically from a string.
I’ve tried with re-pattern, but I can’t escape properly for some reason:
(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
EDIT 2 This little function may help:
(defn escape-all [x]
(str "\\" (reduce #(str %1 "\\" %2) x)))
I got it working by double escaping everything. Oh the joys of double escaping.
I would recommend writing a helper function
str-to-pattern(or whatever you want to call it), that takes a string, double escapes everything it needs to, and then callsre-patternon it.Edit: making a string to pattern function
There are plenty of ways to do this, below is just one example. I start by making an smap of regex escape chars to their string replacement. An “smap” isn’t an actual type, but functionally it’s a map we will use to swap “old values” with “new values”, where “old values” are members of the keys of the smap, and “new values” are corresponding members of the vals of smap. In our case, this smap looks like
{\( "\\(", \) "\\)" ...}.Next is the actual function. I use the above smap to replace items in the string passed to it, then convert that back into a string and make a regex pattern out of it. I think the
->>macro makes the code more readable, but that’s just a personal preference.