Pregunta:
Quiero usar rx
para crear expresiones regulares con valores de tiempo de ejecución.
Actualmente, estoy haciendo esto:
(setq strings '("foo" "bar" "baz"))
(eval `(rx symbol-start (or ,@strings) symbol-end))
Sin embargo, prefiero evitar usar eval
. Encontré rx-to-string
, pero no está claro qué FORMULARIO debería escribir:
;; error: Unknown rx form `symbol-start
(rx-to-string '(symbol-start (or ,@strings) symbol-end))
¿Cómo construyo una expresión rx
en tiempo de ejecución?
Respuesta:
rx-to-string
toma una forma de expresión regular como argumento. La sintaxis es la misma que la del argumento de rx
.
(rx-to-string '(or "foo" "bar"))
"\\(?:\\(?:bar\\|foo\\)\\)"
Lo que intentó pasar no es un formulario regexp, sino una lista de formularios regexp. Dado que lo que quiere decir es la secuencia de expresiones regulares symbol-start
seguido de una de un montón de cadenas seguido de fin de symbol-end
, debe symbol-start
con la secuencia del operador de sequence
(que puede abreviarse como seq
o :
o extrañamente par and
).
(rx-to-string `(: symbol-start (or ,@strings) symbol-end))
"\\(?:\\_<\\(?:ba[rz]\\|foo\\)\\_>\\)"
rx
es de hecho una pequeña envoltura alrededor de rx-to-string
que opera en tiempo de compilación porque es una macro. Lo que hace que esto sea confuso es que si pasa varios argumentos a rx
, hay un operador de sequence
implícito. La documentación de rx
podría ser aclarada.
(rx (: symbol-start (or "foo" "bar" "baz") symbol-end))
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
(rx symbol-start (or "foo" "bar" "baz") symbol-end)
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"