Como crio um regexp dinâmico com rx?

15

Eu quero usar rxpara criar expressões regulares com valores de tempo de execução.

Atualmente, estou fazendo o seguinte:

(setq strings '("foo" "bar" "baz"))
(eval `(rx symbol-start (or ,@strings) symbol-end))

No entanto, prefiro evitar o uso eval. Eu encontrei rx-to-string, mas não está claro qual FORMULÁRIO devo escrever:

;; error: Unknown rx form `symbol-start
(rx-to-string '(symbol-start (or ,@strings) symbol-end))

Como construo uma rxexpressão em tempo de execução?

Wilfred Hughes
fonte

Respostas:

18

rx-to-stringassume uma forma regexp como argumento. A sintaxe é igual ao argumento de rx.

(rx-to-string '(or "foo" "bar"))
"\\(?:\\(?:bar\\|foo\\)\\)"

O que você tentou passar não é um formulário regexp, mas uma lista de formulários regexp. Como o que você quer dizer é a sequência de expressões regulares symbol-startseguida por uma de várias sequências seguidas por symbol-end, você precisa liderar com o operador de sequência sequence(que pode ser abreviado para seqou :, ou estranhamente até and).

(rx-to-string `(: symbol-start (or ,@strings) symbol-end))
"\\(?:\\_<\\(?:ba[rz]\\|foo\\)\\_>\\)"

rxé de fato um pequeno invólucro rx-to-stringque funciona em tempo de compilação porque é uma macro. O que torna isso confuso é que, se você passar vários argumentos para rx, existe um sequenceoperador implícito . A documentação de rxpoderia ser esclarecida.

(rx (: symbol-start (or "foo" "bar" "baz") symbol-end))
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
(rx symbol-start (or "foo" "bar" "baz") symbol-end)
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
Gilles 'SO- parar de ser mau'
fonte
7
"você passa vários argumentos para rx, existe um operador de sequência implícito" - aha! Essa é a principal pegadinha aqui. Obrigado!
Wilfred Hughes