Come posso creare una regexp dinamica con rx?


15

Voglio usare rxper creare espressioni regolari con valori di runtime.

Attualmente sto facendo questo:

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

Tuttavia, preferirei evitare di usare eval. Ho trovato rx-to-string, ma non è chiaro quale FORM dovrei scrivere:

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

Come faccio a creare rxun'espressione in fase di esecuzione?

Risposte:


18

rx-to-stringprende una forma regexp come argomento. La sintassi è la stessa dell'argomento di rx.

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

Quello che hai provato a passare non è un modulo regexp, ma un elenco di moduli regexp. Poiché ciò che intendi è la sequenza di espressioni regolari symbol-startseguita da una di un gruppo di stringhe seguite da symbol-end, devi guidare con l'operatore sequenza sequence(che può essere abbreviato in seqo :, o stranamente anche and).

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

rxè in effetti un piccolo wrapper rx-to-stringche funziona in fase di compilazione perché è una macro. Ciò che rende confuso questo è che se si passano più argomenti a rx, c'è un sequenceoperatore implicito . La documentazione di rxpotrebbe essere chiarita.

(rx (: symbol-start (or "foo" "bar" "baz") symbol-end))
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
(rx symbol-start (or "foo" "bar" "baz") symbol-end)
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"

7
"passi più argomenti a rx, c'è un operatore di sequenza implicita" - aha! Questo è il gotcha principale qui. Grazie!
Wilfred Hughes,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.