2012-02-01 12 views
5

Załóżmy Mam ciąg RGB (format: # < 2 cyfry hex> < 2 cyfry hex> < 2 cyfry hex>) tak:Emacs Lisp: dopasowanie powtarzającego się wzoru w zwarty sposób?

"#00BBCC" 

i chciałbym aby dopasować i uchwycić jej < 2 cyfry hex> elementy w bardziej zwarty sposób niż za pomocą oczywiste:

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

próbowałem:

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

oraz:

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

Ale najbardziej one dopasowane został pierwszym < cyfry 2 hex> elementem.

Każdy pomysł? Dziękuję Ci.

+0

Dlaczego chcesz to zrobić? Czytelność? – Thomas

+0

Po prostu ciekawość: Zastanawiam się, czy wyrazy regularne mogą pasować do powtarzających się wzorców. – Elena

+1

Problem polega na tym, że nie będziesz w stanie odnosić się do 3 różnych grup, prawda? Jak więc wyodrębnić wartości R, G, B osobno? – Thomas

Odpowiedz

1

Jeśli chcesz uchwycić R, G, B w różnych podgrup, tak aby można było wyodrębnić je za pomocą (match-string group), trzeba mieć trzy różne grupy nawiasów w twoim wyrobie w pewnym momencie.

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

W przeciwnym razie, jeśli używasz powtarzacie takie jak

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

masz tylko jedną grupę, a po meczu będzie zawierać tylko wartość ostatniego meczu. Tak więc, powiedzmy, jeśli masz coś na wzór

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

będzie dopasować ciąg jak „A0B1C2”, ale (match-string 1) będzie zawierał jedynie treść ostatniego meczu, czyli „C2”, ponieważ także wyznacza regexp tylko jedna grupa.

W ten sposób masz dwie opcje: użyj zwartego wyrażenia regularnego, takiego jak trzeci, ale wykonaj więcej przetwarzania podłańcucha, aby wyodrębnić liczbę szesnastkową, tak jak sugeruje Sean, lub użyj bardziej złożonego wyrażenia regularnego, na przykład pierwszego, co pozwala wygodniej uzyskać dostęp do trzech pod-meczów.

Jeśli jesteś głównie martwi czytelności kodu, można coś takiego

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

do skonstruowania takiego bardziej złożone wyrażenia regularnego w nieco mniej redundantny sposób, zgodnie z sugestią tripleee zawsze zrobić.

4

Można zrobić regexp krótszy kosztem jakiegoś dodatkowego kodu:

(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

Przyjemny alternatywny pomysł, przebudowuję to. Dodatkowy kod mógł zostać refaktoryzowany w funkcję. – Elena

+4

Dlaczego więc nie "(let (xx" \\ ([[: xdigit:]] \\ {2 \\} \\) ") (string-match (concat" # "xx xx xx) str)))) ? – tripleee

+0

@tripleee To jest to, czego używam w moim kodzie. Właściwie, teraz, kiedy o tym myślę, mógł on zostać refaktoryzowany w bardziej ogólną funkcję niż rozwiązanie sugerowane przez Seana, ponieważ wtedy wzory mogłyby dopasować ciągi o różnej długości. – Elena

Powiązane problemy