February 1, 2021
By: Kevin
脚本编码sed vs babashka
问题: 我们的代码中有namespace中含有_的情况
(ns store-pc.final_custom.final_custom_customer_views
(:require
[re-frame.core :as rf]
[store-pc.final_custom.final_custom_customer_events]
[store-pc.full-custom.components.customer-info :refer [customer-info-page]]))
是违反编码规范的, 因为盘根错节的依赖关系, 手动修改非常麻烦.
我们希望能够通过脚本一次性修改完成, 2021年1月30号我直播修改的时候尝试了sed命令和babashka脚本两种方式, sed脚本处理不完全, 所以最终使用babashka来实现的完整替换.
事后我想sed也是可以完成这个功能的, 只不过需要把ns声明在一行的情况单独处理:
find src -name "*.cljs" | xargs -I {} sed -i'bk' -e "/(ns.*[^)]$/, /)/ s/_/-/g" -e "/(ns.*)$/ s/_/-/g" {}
# (ns.*[^)]$ 对应于(ns 开始, 但是不以)结束的情况, 进行多行查找
# (ns.*)$ 对应于(ns开始, )结束在同一行的情况
对比下面的babashka脚本, sed的方案还是要简单很多
(require '[clojure.java.io :as io] )
(require '[clojure.string :refer [join replace]])
(def matcher (.getPathMatcher
(java.nio.file.FileSystems/getDefault)
"glob:*.{cljs,cljc}"))
(defn get-all-cljs-file-path []
(->> "./src"
io/file ;; 目录生成文件对象
file-seq ;; 遍历所有的文件(文件夹)
(filter #(.isFile %)) ;; 过滤, 只要文件
(filter #(.matches matcher (.getFileName (.toPath %)))) ;; 过滤, clj/cljs/cljc文件
(mapv #(.getPath %))
))
(defn split-file [s]
(loop [input s
output ""
depth 0]
(if (and (zero? depth)
(seq output)
(= \) (last output)))
[output (join input)]
(recur (rest input)
(str output (first input))
(case (first input)
\( (inc depth)
\) (dec depth)
depth)
))))
(defn process-file [file]
(let [src-str (slurp file)
[ns rest] (split-file src-str)]
(spit file (str (replace ns "_" "-")
rest))))
(->> (get-all-cljs-file-path)
(mapv process-file))
;;(first-sexp "(ns a_b_c (+ 111)) () []1")
;; => ["(ns a_b_c (+ 111))" " () []1"]
;; -> (ns a_b_c (+ 1 1))
希望对大家有启发.