Как я могу получить позиции совпадений регулярных выражений в ClojureScript?

В Clojure я мог бы использовать что-то вроде этого решения: ">Компактный код Clojure для совпадений регулярных выражений и их положения в строке, т.е. создание re-matcher и извлечение информации из него, но похоже, что re-matcher не реализован в ClojureScript. Что было бы хорошим способом сделать то же самое в ClojureScript?

Изменить:

В итоге я написал дополнительную функцию, чтобы сохранить модификаторы регулярного выражения, поскольку оно поглощается re-pos:

(defn regex-modifiers
  "Returns the modifiers of a regex, concatenated as a string."
  [re]
  (str (if (.-multiline re) "m")
       (if (.-ignoreCase re) "i")))

(defn re-pos
  "Returns a vector of vectors, each subvector containing in order:
   the position of the match, the matched string, and any groups
   extracted from the match."
  [re s]
  (let [re (js/RegExp. (.-source re) (str "g" (regex-modifiers re)))]
    (loop [res []]
      (if-let [m (.exec re s)]
        (recur (conj res (vec (cons (.-index m) m))))
        res))))

person Henrik    schedule 11.09.2013    source источник


Ответы (1)


Вы можете использовать метод .exec объекта JS RegExp. Возвращенный объект соответствия содержит свойство index, соответствующее индексу совпадения в строке.

В настоящее время clojurescript не поддерживает создание литералов регулярных выражений с флагом режима g (см. CLJS-150), поэтому вам нужно использовать конструктор RegExp. Вот реализация clojurescript функции re-pos со связанной страницы:

(defn re-pos [re s]
  (let [re (js/RegExp. (.-source re) "g")]
    (loop [res {}]
      (if-let [m (.exec re s)]
        (recur (assoc res (.-index m) (first m)))
        res))))

cljs.user> (re-pos "\\w+" "The quick brown fox")
{0 "The", 4 "quick", 10 "brown", 16 "fox"}
cljs.user> (re-pos "[0-9]+" "3a1b2c1d")
{0 "3", 2 "1", 4 "2", 6 "1"}
person mtyaka    schedule 11.09.2013
comment
Спасибо! Это отлично! Единственная проблема с этим решением заключается в том, что для него требуется строка, а не литерал регулярного выражения, что делает его несовместимым с re-seq & co. Знаете ли вы, есть ли какой-либо надежный способ преобразования литерала регулярного выражения в строку для использования в этой функции? - person Henrik; 11.09.2013
comment
Свойство source объектов regexp возвращает источник текста. Я обновил ответ, чтобы re-pos принимал объект регулярного выражения вместо строки. - person mtyaka; 11.09.2013
comment
Вы прославляете своих предков. - person Henrik; 11.09.2013
comment
Предостережение, это будет бесконечный цикл: (re-pos #"" "anything") - person Blake Miller; 25.07.2018