Clojure 实现通配符匹配
2017-06-15 本文已影响96人
BlindingDark
(defn cutting
[str result]
(if (empty? str)
result
(recur (rest str) (conj result str))))
(defn cutting-string
[string]
(map #(apply str %) (cutting string [])))
(defn star-end-pattern
"匹配结尾是星号的情况"
[pattern pattern-point]
(if (and (< pattern-point (count pattern))
(= \* (nth pattern pattern-point)))
(recur pattern (inc pattern-point))
(>= pattern-point (count pattern))))
(defn next-star-point
"获得最右方的星号位置"
[pattern pattern-point]
(cond (>= (inc pattern-point) (count pattern))
pattern-point,
(= \* (nth pattern (inc pattern-point)))
(recur pattern (inc pattern-point)),
(not= \* (nth pattern (inc pattern-point)))
pattern-point))
(defn match
"匹配带通配符的字符串"
[pattern string pattern-point string-point]
(let [str-length (count string),
pattern-length (count pattern)]
(cond
(>= string-point str-length) ;;字符串到了末尾(结束)的情况,可以继续被 * 匹配
(star-end-pattern pattern pattern-point),
(>= pattern-point pattern-length) false, ;;如果匹配串结束但是字符串没有结束
(= \* (nth pattern pattern-point)) ;; 通配符匹配
(let [p-behind-star (subs pattern (inc (next-star-point pattern pattern-point))),
strs (cutting-string (subs string string-point str-length)),
result (map #(match p-behind-star % 0 0)
(cutting-string (subs string string-point str-length)))]
(not (empty? (filter true? result))))
(not= (nth pattern pattern-point) (nth string string-point)) false, ;;非通配符匹配失败
:else (recur pattern string (inc pattern-point) (inc string-point)))))
(defn match-filename
[fmt file]
(match fmt file 0 0))
简单测试
(match-filename "*a*b" "aababa")
=> false
(match-filename "*a*b" "aaab")
=> true
(match-filename "*a*b" "aabab")
=> true
(match-filename "*a*b*" "aabab")
=> true
(match-filename "*a*b*" "ab")
=> true