2012-07-26 26 views
5

Nếu tôi cố gắng nàyngoặc Thoát trong Clojure

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

hay này

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

Tôi đã Clojure phàn nàn rằng có một chưa từng có/không khép kín ). Tại sao các dấu ngoặc được đánh giá trong chuỗi đơn giản này? Làm thế nào để thoát khỏi chúng? Cảm ơn

EDIT: Trong khi thoát công trình trong cú pháp clojure cụ thể (#""), nó không hoạt động với Pattern/compile cú pháp mà tôi cần phải bởi vì tôi phải biên dịch patter regex động từ một chuỗi.

Tôi đã thử với re-pattern, nhưng tôi không thể thoát khỏi đúng đối với một số lý do:

(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 chức năng nhỏ này có thể giúp:

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

Ngoài ra, tôi không nghĩ bạn cần nhập, bạn chỉ có thể sử dụng chức năng 'tái mẫu 'của Clojure. –

+0

bạn nói đúng. tôi vẫn không thể làm được. vui lòng xem bản chỉnh sửa của tôi. – pistacchio

Trả lời

10

Tôi đã làm cho nó hoạt động bằng cách thoát đôi mọi thứ. Oh những niềm vui của thoát kép.

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

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

Tôi muốn giới thiệu cách viết một hàm helper str-to-pattern (hoặc bất cứ điều gì bạn muốn gọi nó), mà phải mất một chuỗi, thoát đôi mọi thứ nó cần phải, và sau đó gọi re-pattern trên đó.

Edit: thực hiện một chuỗi chức năng mô hình
Có rất nhiều cách để làm điều này, dưới đây chỉ là một ví dụ. Tôi bắt đầu bằng cách tạo một smap các ký tự thoát regex để thay thế chuỗi của họ. Một "smap" không phải là một loại thực tế, nhưng chức năng đó là bản đồ chúng tôi sẽ sử dụng để hoán đổi "giá trị cũ" với "giá trị mới", trong đó "giá trị cũ" là thành viên của khóa của smap và "giá trị mới" là thành viên tương ứng của các vals smap. Trong trường hợp của chúng tôi, smap này trông giống như {\("\\(", \) "\\)" ...}.

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

Tiếp theo là chức năng thực tế. Tôi sử dụng smap trên để thay thế các mục trong chuỗi được truyền cho nó, sau đó chuyển đổi đó trở lại thành một chuỗi và làm cho một mẫu regex ra khỏi nó. Tôi nghĩ rằng macro ->> làm cho mã dễ đọc hơn, nhưng đó chỉ là sở thích cá nhân.

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

bạn có chắc lỗi là từ người đọc (tức là từ clojure chính nó)?

regexps sử dụng dấu ngoặc đơn và chúng cũng phải khớp với dấu ngoặc đơn. tôi sẽ đoán lỗi là cominng từ mã cố gắng để biên dịch regexp.

nếu bạn muốn thoát khỏi dấu ngoặc trong một regexp, sử dụng một backquote: (def p #"\)[email protected]#$%^&*\(\)")

[cập nhật] ah, xin lỗi, có lẽ bạn cần thoát đôi như ngày Omri.

+0

cảm ơn, nhưng bạn có thể vui lòng xem chỉnh sửa của tôi không? – pistacchio

+0

@pistacchio Tôi nghĩ bạn sẽ phải trốn thoát gấp đôi. Tôi có thể đề nghị viết một hàm trợ giúp 'str-to-pattern' (hoặc một số tên tương tự) có một chuỗi, double escape những thứ cần thiết, và sau đó gọi' re-pattern' trên nó. –

+0

Tôi không thể tìm thấy chức năng như vậy ở đây http://clojure.org/cheatsheet – pistacchio

1

Tất cả các phiên bản của Java mà Clojure hỗ trợ nhận \Q để bắt đầu một vùng niêm yết và \E để kết thúc khu vực trích dẫn.Điều này cho phép bạn làm điều gì đó như thế này:

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

Nếu bạn đang sử dụng (re-pattern) thì điều này sẽ làm việc:

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

Nếu bạn đang lắp ráp một biểu thức chính quy từ một chuỗi có nội dung bạn don' t biết thì bạn có thể sử dụng phương pháp quote trong java.util.regex.Pattern:

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

Dưới đây là một ví dụ về điều này từ REPL tôi:

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]#$%^&*()" 
Các vấn đề liên quan