我需要一个函数,当给定一个基本目录和另一个路径时,我已经完成了一个与绝对路径匹配的简化版本,但希望也能够智能地处理“..”。还有“.”在路上。我不知道最好的方法是什么
一些例子:
(relative-path "example" "example/hello") => "hello"
(relative-path "example" "../example/hello") => "hello"
(relative-path "example" "/usr/local") => "../../../usr/local"发布于 2014-10-03 14:13:02
经过一段时间的反复试验,我终于想出了答案:
(require '[clojure.java.io :as io]
'[clojure.string :as string])
(defn interpret-dots
([v] (interpret-dots v []))
([v output]
(if-let [s (first v)]
(condp = s
"." (recur (next v) output)
".." (recur (next v) (pop output))
(recur (next v) (conj output s)))
output)))
(defn drop-while-matching [u v]
(cond (or (empty? u) (empty? v)) [u v]
(= (first u) (first v))
(recur (rest u) (rest v))
:else [u v]))
(defn path-vector [path]
(string/split (.getAbsolutePath (io/file path))
(re-pattern (System/getProperty "file.separator"))))
(defn relative-path [root other]
(let [[base rel] (drop-while-matching (interpret-dots (path-vector root))
(interpret-dots (path-vector other)))]
(if (and (empty? base) (empty? rel))
"."
(->> (-> (count base)
(repeat "..")
(concat rel))
(string/join (System/getProperty "file.separator")))))用法:
(relative-path "example/repack.advance/resources"
"example/repack.advance/resources/eueueeueu/oeuoeu")
;;=> "eueueeueu/oeuoeu"
(relative-path "example/repack.advance/resources"
"/usr/local")
;;=> "../../../../../../../../usr/local"https://stackoverflow.com/questions/26170493
复制相似问题