Bagaimana cara membuat regexp dinamis dengan rx?

15

Saya ingin menggunakan rxuntuk membuat ekspresi reguler dengan nilai runtime.

Saat ini, saya melakukan ini:

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

Namun, saya lebih suka menghindari menggunakan eval. Saya telah menemukan rx-to-string, tetapi tidak jelas FORMULIR apa yang harus saya tulis:

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

Bagaimana cara membangun rxekspresi saat runtime?

Wilfred Hughes
sumber

Jawaban:

18

rx-to-stringmengambil bentuk regexp sebagai argumen. Sintaksnya sama dengan argumen dari rx.

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

Apa yang Anda coba lewati bukanlah formulir regexp, tetapi daftar form regexp. Karena yang Anda maksud adalah urutan ekspresi reguler symbol-startdiikuti oleh salah satu dari sekelompok string diikuti oleh symbol-end, Anda harus memimpin dengan operator urutan sequence(yang dapat disingkat menjadi seqatau :, atau bahkan aneh and).

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

rxsebenarnya pembungkus kecil di sekitar rx-to-stringyang beroperasi pada waktu kompilasi karena makro. Apa yang membuat ini membingungkan adalah bahwa jika Anda melewati beberapa argumen rx, ada sequenceoperator implisit . Dokumentasi rxdapat diklarifikasi.

(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- berhenti menjadi jahat'
sumber
7
"Anda meneruskan beberapa argumen ke rx, ada operator urutan tersirat" - aha! Itulah gotcha utama di sini. Terima kasih!
Wilfred Hughes