regex 通过re-seq re-pattern查找字符串中函数名的确切用法- Clojure

c3frrgcw  于 2023-06-07  发布在  其他
关注(0)|答案(2)|浏览(124)

我的f函数并不像我预期的那样工作。我想在给定的字符串中找到精确的匹配,但我的f函数工作得很奇怪:
让我大致解释一下我尝试做的事情,将在slurp函数中以args的形式给予本地存储库路径,然后读取该位置中的所有cljcljscljc文件,将它们解析为字符串,然后尝试汇总Clojure核心函数的使用次数。我希望我已经解释清楚我想做什么。
编辑1:我将尝试实现纯f函数。编辑2:对不起,我组织的问题像MRE。

(defn f "searchs the given value(inside !type atom) inside given text(vector-0f-texts)"
  [regex text]
  (count (re-seq (re-pattern regex) text)))

(def function-text
  "str-path  str")

(f "str" function-text)
=> 2
;expected => 1
x0fgdtte

x0fgdtte1#

如果你想非常准确,reg-exp只能带你到这里。你最好使用解析器。
对于琐碎的任务,您可以使用核心阅读器,例如。read-string。这没有任何线索,实际上是怎么回事(例如。这是一个函数名还是一个字母绑定),但至少给了你它们是什么(不需要处理那里的每一个单词障碍或排除字符串)。对于一些符号的简单计数,您可以使用如下内容:

(->> (read-string s) ; `s` is from your example
     (tree-seq (some-fn list? vector? map?) seq) ; "flatten" the tree
     (filter #{'map 'acc}) ; only pick symbols with the names map or acc
     (frequencies)
     (prn))

如果你对此非常认真,你可以考虑像这样的库:

这是一个使用tools的示例。analyzer:

(ns tana.core
  (:require [clojure.tools.analyzer.jvm :as ana]))

(defn ana-branch?
  "tree-seq branch? predicate for clojure.tools.analyzer.jmv/analyze"
  [node]
  (or (and (map? node) (:children node))
      (vector? node)))

(defn ana-children
  "tree-seq children extractor for clojure.tools.analyzer.jmv/analyze"
  [node]
  (if (map? node)
    (map node (:children node))
    (seq node)))

(defn ana-tree-seq
  "Create a tree-seq over the result from clojure.tools.analyzer.jmv/analyze"
  [root]
  (tree-seq ana-branch? ana-children root))

(defn ana-var=-fn
  "Creates a predicate function to check, if the given node is a :var :op and the symbol of :var is the given sym"
  [sym]
  (fn [node]
    (and (map? node)
         (= :var (:op node))
         (= sym (symbol (:var node))))))

; ---

(->> '(->>
       [{:a 1}]
       (map (fn [map]
              (update map :a vector)))
       (mapcat (partial (comp (partial map inc) :a))))

     (ana/analyze)
     (ana-tree-seq)
     (filter (ana-var=-fn 'clojure.core/map))
     (count))
; ⇒ 2
31moq8wy

31moq8wy2#

为了让它更清楚,我张贴这作为一个答案,而不仅仅是一个评论。
根据这个定义:

(defn f "searchs the given value(inside !type atom) inside given text(vector-0f-texts)"
  [pattern text]
  (count (re-seq (re-pattern pattern) text)))

并利用这段文字

(def function-text 
  "(defn idx->meta [pair-col]
     (->> pair-col
          (apply hash-map)
          (reduce-kv (fn [acc k v]
                       (let [idx       k
                             str-vals  (filterv string? (vals v))
                             str-paths (->> str-vals
                                            (map #(clojure.string/split % #\"\")))]
                         (->> str-paths
                              (reduce (fn [acc str-path]
                                        (update-in acc str-path (fnil conj []) v))
                                      acc))))
                     {})
          )
     )")

你可以做一些实验:

(f "with-open" function-text)
;; => 0
(f "int?" function-text)
;; => 3
(f "int\\?" function-text)
;; => 0

特别地,?是正则表达式中的一个特殊字符,它意味着前一个模式的“零次或一次重复”。这不是Clojure或Java特有的,它是一个标准的正则表达式行为。

UPDATE:符号的精确匹配精确匹配可能有点棘手,但这可以通过排除Clojure符号中所有有效的字符来实现:

(defn f
  "searchs the given value(inside !type atom) inside given text(vector-0f-texts)"
  [pattern text]
  ;; See https://clojure.org/reference/reader#_symbols for valid characters in Clojure symbols
  (count (re-seq (re-pattern (str "\\Q" pattern "\\E" "[^a-zA-Z0-9*+!\\-_'?]")) text)))

它还使用“\Q”和“\E”来模拟Pattern/quote(参见cfrick的注解)。
顺便说一句,为了进行更严肃的分析,我会看看https://github.com/clj-kondo/clj-kondo,这里有一些快速的实验:https://github.com/jumarko/clojure-experiments/blob/develop/src/clojure_experiments/linters/clj_kondo.clj#L1

相关问题