Как мне создать динамическое регулярное выражение с rx?

15

Я хочу использовать rxдля создания регулярных выражений со значениями времени выполнения.

В настоящее время я делаю это:

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

Тем не менее, я бы предпочел не использовать eval. Я нашел rx-to-string, но не ясно, какую форму я должен написать:

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

Как мне построить rxвыражение во время выполнения?

Уилфред Хьюз
источник

Ответы:

18

rx-to-stringпринимает форму регулярного выражения в качестве аргумента. Синтаксис такой же, как аргумент rx.

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

То, что вы пытались передать, это не форма регулярного выражения, а список форм регулярного выражения. Поскольку вы имеете в виду последовательность регулярных выражений, symbol-startза которой следует одна из множества строк, за которыми следует symbol-end, вам нужно привести с оператором последовательности sequence(который может быть сокращен до seqили :, или странно даже and).

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

rxна самом деле это крошечная оболочка, rx-to-stringкоторая работает во время компиляции, потому что это макрос. Это сбивает с толку то, что если вы передаете несколько аргументов rx, есть неявный sequenceоператор. Документация rxможет быть уточнена.

(rx (: symbol-start (or "foo" "bar" "baz") symbol-end))
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
(rx symbol-start (or "foo" "bar" "baz") symbol-end)
"\\_<\\(?:ba[rz]\\|foo\\)\\_>"
Жиль "ТАК - перестань быть злым"
источник
8
«Вы передаете несколько аргументов в rx, есть оператор неявной последовательности» - ага! Это главная ошибка здесь. Благодарность!
Уилфред Хьюз