Wie erstelle ich mit rx einen dynamischen regulären Ausdruck?

15

Ich möchte verwenden rx, um reguläre Ausdrücke mit Laufzeitwerten zu erstellen.

Derzeit mache ich das:

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

Ich würde es jedoch lieber vermeiden eval. Ich habe gefunden rx-to-string, aber es ist nicht klar, welches FORMULAR ich schreiben soll:

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

Wie erstelle ich einen rxAusdruck zur Laufzeit?

Wilfred Hughes
quelle

Antworten:

18

rx-to-stringnimmt eine reguläre Ausdrucksform als Argument an. Die Syntax entspricht dem Argument von rx.

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

Was Sie versucht haben zu übergeben, ist kein regulärer Ausdruck, sondern eine Liste von regulären Ausdrücken. Da Sie damit die Folge von regulären Ausdrücken, symbol-startgefolgt von einer Reihe von Zeichenfolgen symbol-end, meinen , müssen Sie mit dem Sequenzoperator sequence(der mit seqoder abgekürzt werden kann :, oder seltsamerweise sogar and) beginnen.

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

rxist in der Tat ein winziger Wrapper rx-to-string, der zur Kompilierungszeit ausgeführt wird, da es sich um ein Makro handelt. Das Verwirrende daran ist, dass rxes einen impliziten sequenceOperator gibt, wenn Sie mehrere Argumente übergeben . Die Dokumentation von rxkönnte noch geklärt werden.

(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 - hör auf böse zu sein'
quelle
7
"Übergeben Sie mehrere Argumente an rx, gibt es einen impliziten Sequenzoperator" - aha! Das ist das Hauptproblem hier. Vielen Dank!
Wilfred Hughes