2012-02-01 10 views
5

Supongamos que tengo una cadena RGB (formato: # < 2 dígitos hexadecimales> < 2 dígitos hexadecimales> < 2 dígitos hexadecimales>) como esto:Emacs Lisp: ¿coincide con un patrón repetido de forma compacta?

"#00BBCC" 

y me gustaría hacer coincidir y capturar su < 2 dígitos hexadecimales> elementos en una forma más compacta que mediante el uso de lo obvio:

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

que he probado:

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

y:

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

Pero lo más que común ha sido el primer> elemento < dígitos 2 hexagonales.

¿Alguna idea? Gracias.

+0

¿Por qué quieres hacer eso? Para la legibilidad? – Thomas

+0

Simplemente curiosidad: me pregunto si las expresiones regulares pueden coincidir con los patrones repetidos. – Elena

+1

El problema es que no podrías referirte a 3 grupos diferentes, ¿no? Entonces, ¿cómo extraerías los valores R, G, B por separado? – Thomas

Respuesta

1

Si desea capturar R, G, B en diferentes subgrupos, de manera que se puede extraer usando (match-string group), es necesario tener tres grupos de paréntesis diferentes en tu expresión regular en algún momento.

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

De lo contrario, si se utiliza un patrón de repetición, como

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

que tiene un solo grupo, y después del partido que sólo contendrá el valor del último partido. Así, por ejemplo, si tiene algo en la línea de

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

que coincidirá con una cadena como "A0B1C2", pero (match-string 1) sólo contendrá los contenidos del último partido, es decir, "C2", debido a que los define expresiones regulares solo un grupo

Por lo tanto, básicamente tiene dos opciones: use una expresión regular compacta, como la tercera, pero haga un poco más de subcadena para extraer el número hexadecimal como sugiere Sean, o use una expresión regular más compleja, como la primera, que te permite acceder a las tres subcletas más cómodamente.

Si está más preocupado por la legibilidad del código, siempre se puede hacer algo como

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

para construir una expresión regular como más compleja de una manera algo menos redundante, según la sugerencia de tripleee.

4

Puede hacer que la expresión regular más corta a expensas de algún código extra:

(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

Buena idea alternativa, estoy votando esto. El código adicional podría refactorizarse en una función. – Elena

+4

¿Por qué no? '(Let (xx" \\ ([[: xdigit:]] \\ {2 \\} \\) ") (string-match (concat" # "xx xx xx) str)))' ? – tripleee

+0

@tripleee Eso es lo que estoy usando en mi código. En realidad, ahora que lo pienso, podría refactorizarse en una función más genérica que la solución sugerida por Sean, porque entonces los patrones podrían coincidir con cadenas de diferentes longitudes. – Elena