Comment créer une expression rationnelle dynamique avec rx?

15

Je souhaite utiliser rxpour créer des expressions régulières avec des valeurs d'exécution.

Actuellement, je fais ceci:

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

Cependant, je préfère éviter d'utiliser eval. J'ai trouvé rx-to-string, mais la forme que je dois écrire n'est pas claire:

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

Comment créer une rxexpression au moment de l'exécution?

Wilfred Hughes
la source

Réponses:

18

rx-to-stringprend une forme d'expression régulière comme argument. La syntaxe est la même que l'argument de rx.

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

Ce que vous avez essayé de transmettre n'est pas un formulaire d'expression régulière, mais une liste de formulaires d'expression régulière. Étant donné que vous voulez dire la séquence d'expressions régulières symbol-startsuivie d'une chaîne de chaînes suivie symbol-end, vous devez diriger avec l'opérateur de séquence sequence(qui peut être abrégé en seqou :, ou bizarrement même and).

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

rxest en fait un petit wrapper rx-to-stringqui fonctionne au moment de la compilation car c'est une macro. Ce qui rend cela déroutant, c'est que si vous passez plusieurs arguments à rx, il existe un sequenceopérateur implicite . La documentation de rxpourrait être clarifiée.

(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- arrête d'être méchant'
la source
8
"vous passez plusieurs arguments à rx, il y a un opérateur de séquence implicite" - aha! C'est le principal problème ici. Merci!
Wilfred Hughes