2024 年 Clojure 调查问卷! 中分享您的看法。

欢迎!有关如何使用此服务的更多信息,请参阅 关于 页面。

+1
ClojureScript
{{clojure.string/split}} 在有限制的情况下不能正确按照如下方式分割字符串:


(clojure.string/split "quaqb" #"q(?!u)") ; <- 匹配不跟在 'u' 后的 'q'
;;=> ["qua" "b"]

(clojure.string/split "quaqb" #"q(?!u)" 2)
;;=> ["" "uaqb"]


第一个案例的结果是我们想要的,但第二个案例的结果是错误的。
因为,如果有限制,它会使用自己的例行程序而不是 JavaScript 的 {{String.prototype.split}} 函数来分割字符串。
而且,当在正则表达式中使用 [前瞻或回溯](https://regexper.cn/lookaround.html) 时,该例行程序会有问题。


;; clojure.string/split
(let [re #"q(?!u)"]
  (loop [s "quaqb"
         limit 2
         parts []]
    (if (== 1 limit)
      (conj parts s)
      (let [m (re-find re s)] ; <- 1!
        (if-not (nil? m)
          (let [index (.indexOf s m)] ; <- 2!
            (recur (.substring s (+ index (count m)))
                   (dec limit)
                   (conj parts (.substring s 0 index))))
          (conj parts s))))))
;;=> ["" "uaqb"]

(re-find #"q(?!u)" "quaqb") ; <- 1!
;; => "q"

(.indexOf "quaqb" "q") ; <- 2!
;;=> 0


我们应该从 JavaScript 的 {{RegExp.prototype.exec}} 函数中获取索引,而不是自己计算。


;; clojure.string/split
(let [re #"q(?!u)"]
  (loop [s "quaqb"
         limit 2
         parts []]
    (if (== 1 limit)
      (conj parts s)
      (let [m (.exec re s)]
        (if-not (nil? m)
          (let [index (.-index m)]
            (recur (.substring s (+ index (count (aget m 0))))
                   (dec limit)
                   (conj parts (.substring s 0 index))))
          (conj parts s))))))
;;=> ["qua" "b"]


i 在 V8、Spidermonkey、Nashorn 上进行了测试。

6 个答案

0

评论者:vmfhrmfoaj

添加补丁

0

评论者:vmfhrmfoaj

我更新了补丁以更改测试

0

评论者:vmfhrmfoaj

我更新了补丁以修复边缘情况

0

评论者:vmfhrmfoaj

我更新了补丁以修复错误并添加测试
(很抱歉补丁频繁更新,我以为这很容易)

0

评论者:vmfhrmfoaj

更新补丁

0
参考:[https://clojure.atlassian.net/browse/CLJS-2528](https://clojure.atlassian.net/browse/CLJS-2528)(由vmfhrmfoaj报告)
...