用于正则表达式匹配的紧凑Clojure代码及其在字符串中的位置

时间:2010-07-16 05:37:16

标签: regex clojure

Stuart Halloway举了个例子

(re-seq #"\w+" "The quick brown fox")

作为在Clojure中查找正则表达式匹配的匹配的自然方法。在他的书中,这种结构与对匹配器的迭代形成对比。如果所有人都关心的是一系列比赛,这将是很棒的。但是,如果我想要匹配及其在字符串中的位置怎么办?是否有更好的方法可以让我利用java.util.regex中的现有功能,对原始字符串中的每个索引采用类似于序列的理解?换句话说,人们想输入类似

的内容
  

(re-seq-map#“[0-9] +”“3a1b2c1d”)

将返回一个地图,其中键作为位置,值作为匹配,例如

{0 "3", 2 "1", 4 "2", 6 "1"}

现有的库中是否有一些实现,或者我应该写它(不应该是代码行)?

2 个答案:

答案 0 :(得分:10)

您可以从java.util.regex.Matcher对象中获取所需数据。

user> (defn re-pos [re s]
        (loop [m (re-matcher re s)
               res {}]
          (if (.find m)
            (recur m (assoc res (.start m) (.group m)))
            res)))
#'user/re-pos
user> (re-pos #"\w+" "The quick brown fox")
{16 "fox", 10 "brown", 4 "quick", 0 "The"}
user> (re-pos #"[0-9]+" "3a1b2c1d")
{6 "1", 4 "2", 2 "1", 0 "3"}

答案 1 :(得分:1)

您可以将任何函数应用于java.util.regex.Matcher对象并返回其结果(simmilar到Brian的解决方案,但没有明确的loop):

user=> (defn re-fun
         [re s fun]
         (let [matcher (re-matcher re s)]
           (take-while some? (repeatedly #(if (.find matcher) (fun matcher) nil)))))
#'user/re-fun

user=> (defn fun1 [m] (vector (.start m) (.end m)))
#'user/fun1

user=> (re-fun #"[0-9]+" "3a1b2c1d" fun1)
([0 1] [2 3] [4 5] [6 7])

user=> (defn re-seq-map
         [re s]
         (into {} (re-fun re s #(vector (.start %) (.group %)))))

user=> (re-seq-map #"[0-9]+" "3a1b2c1d")
{0 "3", 2 "1", 4 "2", 6 "1"}