2012-07-26 73 views
5

摆脱括号如果我试试这个Clojure中

(import java.util.regex.Pattern) 
(Pattern/compile ")[email protected]#$%^&*()") 

或本

(def p #")[email protected]#$%^&*()") 

我已经Clojure的抱怨,有一个无与伦比/未关闭)。为什么在这个简单的字符串中评估括号?如何逃避他们?由于

编辑:当逃脱的具体Clojure的语法(#"")的作品,它不与Pattern/compile语法,我确实需要,因为我有一个字符串动态编译正则表达式拍打工作。

我试着re-pattern,但我不能因为某些原因正确逃生:

(re-pattern "\)[email protected]#$%^&*\(\)") 
    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这个小功能可以帮助:

(defn escape-all [x] 
    (str "\\" (reduce #(str %1 "\\" %2) x))) 
+1

另外,我不认为你需要导入,你可以使用Clojure的're-pattern'函数。 – 2012-07-26 15:05:04

+0

你是对的。仍然,我无法让它工作。请看我的编辑。 – pistacchio 2012-07-26 15:06:30

回答

10

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

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

=> (re-find (re-pattern "\\)\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)") 
      ")[email protected]#$%^&*()") 
=> ")[email protected]#$%^&*()" 

我会建议写一个辅助函数str-to-pattern(或任何你想将它命名),这需要一个字符串,双逃脱它的一切需要,然后就可以调用re-pattern

编辑:做一个字符串模式功能
有很多方法可以做到这一点,下面就是一个例子。我首先制作了一个正则表达式转义字符串来替换字符串。一个“smap”不是一个实际的类型,但在功能上它是一张我们将用来将“旧值”与“新值”交换的映射,其中“旧值”是smap键的成员,“新值”是smap vals的相应成员。在我们的例子中,这个smap看起来像{\("\\(", \) "\\)" ...}

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

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

(defn str-to-pattern 
    [string] 
    (->> string 
     (replace regex-char-esc-smap) 
     (reduce str) 
     re-pattern)) 
3

你确定的错误来自读者(即来自clojure本身)?

正则表达式使用括​​号,它们也必须在那里匹配。我想这个错误是从试图编译正则表达式的代码中得到的。

如果你想逃避的正则表达式的括号

,使用反引号:(def p #"\)[email protected]#$%^&*\(\)")

[更新]啊,对不起,你可能需要双转义为暗利天。

+0

谢谢,但你能看到我的编辑? – pistacchio 2012-07-26 14:59:44

+0

@pistacchio我认为你必须加倍逃避。我可能会建议编写一个帮助函数'str-to-pattern'(或一些类似的名称)来接收一个字符串,double将它所需的东西转义出来,然后调用're-pattern'。 – 2012-07-26 15:06:45

+0

我在这里找不到这样的功能http://clojure.org/cheatsheet – pistacchio 2012-07-26 15:12:11

1

所有的Java的版本是Clojure的支持承认\Q开始引用区和\E结束引述区域。这允许你做这样的事情:

(re-find #"\Q)[email protected]#$%^&*()\E" ")[email protected]#$%^&*()") 

如果你使用(re-pattern)那么这将工作:

(re-find (re-pattern "\\Q)[email protected]#$%^&*()\\E") ")[email protected]#$%^&*()") 

如果你从一个字符串,其内容你不组装一个正则表达式然后知道你可以在java.util.regex.Pattern使用quote方法:

(re-find (re-pattern (java.util.regex.Pattern/quote some-str)) some-other-str) 

下面是从我REPL这样一个例子:

user> (def the-string ")[email protected]#$%^&*()") 
#'user/the-string 
user> (re-find (re-pattern (java.util.regex.Pattern/quote the-string)) the-string) 
")[email protected]#$%^&*()"