2012-02-01 27 views
5

Giả sử tôi có một chuỗi RGB (định dạng: # < 2 chữ số hex> < 2 chữ số hex> < 2 chữ số hex>) như thế này:Emacs Lisp: khớp một mẫu lặp lại một cách gọn gàng?

"#00BBCC" 

và tôi muốn để phù hợp và chụp < của nó 2 chữ số hex> yếu tố một cách nhỏ gọn hơn bằng cách sử dụng rõ ràng:

"#\\([[:xdigit:]\\{2\\}]\\)\\([[:xdigit:]\\{2\\}]\\)\\([[:xdigit:]\\{2\\}]\\)" 

tôi đã thử:

"#\\([[:xdigit:]]\\{2\\}\\)\\{3\\}" 

và:

"#\\(\\([[:xdigit:]]\\{2\\}\\)\\{3\\}\\)" 

Nhưng hầu hết họ xuất hiện đã trở thành < chữ số 2 hex> phần tử đầu tiên.

Bất kỳ ý tưởng nào? Cảm ơn bạn.

+0

Tại sao bạn muốn làm điều đó? Để dễ đọc? – Thomas

+0

Chỉ tò mò: Tôi tự hỏi liệu regexps có thể phù hợp với các mẫu lặp lại hay không. – Elena

+1

Vấn đề là bạn sẽ không thể tham khảo 3 nhóm khác nhau sau đó, phải không? Vậy làm thế nào bạn sẽ trích xuất các giá trị R, G, B một cách riêng biệt? – Thomas

Trả lời

1

Nếu bạn muốn chụp R, G, B trong các phân nhóm khác nhau, do đó bạn có thể trích xuất chúng bằng cách sử (match-string group), bạn cần để có ba nhóm dấu ngoặc đơn khác nhau trong regexp của bạn tại một số điểm.

\(...\)\(...\)\(...\) 

Ngược lại, nếu bạn sử dụng một mô hình lặp lại như

\(...\)\{3\} 

bạn chỉ có một nhóm, và sau khi trận đấu nó sẽ chỉ chứa giá trị của trận đấu cuối cùng. Vì vậy, nói rằng, nếu bạn có một cái gì đó dọc theo dòng của

\([[:xdigit:]]\{2\}\)\{3\} 

nó sẽ phù hợp với một chuỗi như "A0B1C2", nhưng (match-string 1) sẽ chỉ chứa các nội dung của trận đấu cuối cùng, tức là "C2", bởi vì các định nghĩa regexp chỉ một nhóm. Vì vậy, về cơ bản bạn có hai lựa chọn: sử dụng regexp nhỏ gọn, chẳng hạn như số thứ ba, nhưng thực hiện thêm một số chuỗi con để trích xuất số hex như Sean gợi ý hoặc sử dụng regexp phức tạp hơn, chẳng hạn như cụm từ đầu tiên của bạn, cho phép bạn truy cập vào ba kết hợp phụ thuận tiện hơn.

Nếu bạn chủ yếu lo lắng về mã dễ đọc, bạn luôn có thể làm điều gì đó như

(let ((hex2 "\\([[:xdigit:]]\\{2\\}\\)")) 
    (concat "#" hex2 hex2 hex2)) 

để xây dựng một regexp phức tạp hơn như vậy trong một cách nào ít dư thừa, theo đề nghị của tripleee.

4

Bạn có thể làm cho regexp ngắn tại các chi phí của một số mã thêm:

(defun match-hex-digits (str) 
    (when (string-match "#[[:xdigit:]]\\{6\\}" str) 
    (list (substring (match-string 0 str) 1 3) 
      (substring (match-string 0 str) 3 5) 
      (substring (match-string 0 str) 5 7)))) 
+1

Ý tưởng thay thế tuyệt vời, tôi đang upvoting điều này. Mã bổ sung có thể được cấu trúc lại thành một hàm. – Elena

+4

Tại sao không thì '(let (xx" \\ ([[: xdigit:]] \\ {2 \\} \\) ") (chuỗi khớp nối (concat" # "xx xx xx) str)))' ? – tripleee

+0

@tripleee Đó là những gì tôi đang sử dụng trong mã của mình. Trên thực tế, bây giờ tôi nghĩ về nó, nó có thể được tái cấu trúc trong một chức năng chung chung hơn so với các giải pháp được đề xuất bởi Sean, bởi vì sau đó các mẫu có thể phù hợp với chuỗi độ dài khác nhau. – Elena

Các vấn đề liên quan