这是ClojureScript中re-seq实现中的一个bug
(defn re-seq
"Returns a lazy sequence of successive matches of re in s."
[re s]
(let [match-data (re-find re s)
match-idx (.search s re)
match-str (if (coll? match-data) (first match-data) match-data)
post-idx (+ match-idx (max 1 (count match-str)))
post-match (subs s post-idx)]
(when match-data (lazy-seq (cons match-data (when (<= post-idx (count s)) (re-seq re post-match)))))))
问题出现在它递归地使用字符串剩余部分调用re-seq的地方,这样做意味着^[a-f]
将再次匹配这个新的较短的字符串。
一个解决方案是让您的正则表达式具有黏性
(js/RegExp. #"^." "y")
这会让后续使用您的正则表达式时知道之前匹配的位置,请注意您必须谨慎地放置此代码,因为它需要创建在正确的位置,不能全局!如果是全局的,你可能会遇到这种怪异的状态问题
(let [re (js/RegExp. #"^." "y")]
[(re-seq re "cccc")
(re-seq re "abbb")])
;; => [("c" "c") nil]
(我完全不能解释!)
可能re-seq
的一个替代实现会为您创建这个初始副本
(defn re-seq2
"Returns a lazy sequence of successive matches of re in s."
[re s]
(let [re-seq* (fn re-seq* [re s]
(let [match-data (re-find re s)
match-idx (.search s re)
match-str (if (coll? match-data) (first match-data) match-data)
post-idx (+ match-idx (max 1 (count match-str)))
post-match (subs s post-idx)]
(when match-data (lazy-seq (cons match-data (when (<= post-idx (count s)) (re-seq* re post-match)))))))]
(re-seq* (js/RegExp. re "y") s)))
(let [re #"^."]
[(re-seq2 re "cccc")
(re-seq2 re "abbb")])
;; => [("c") ("a")]