正则表达式在Clojure中的应用

  关于正则表达式基础概念,在我的另一篇文章 http://blog.csdn.net/zdplife/article/details/51866141有相关的总结,最近在学习函数式编程语言Clojure,因此将Clojure中经常使用到正则表达式的函数总结如下:
1. re-find函数:
re-find函数用于查找字符串中满足给定正则表达式的第一个匹配的内容并返回:

(re-find #"[a-e]%d*" "whe12343ywe123weh")
;=> "e12343"

  在字符串“whe12343ywe123weh”中,有两处都满足正则表达式”[a-e]%d*”,分别是: “e12343”和“e123”,但是re-find函数只匹配其中的第一项。
  如果正则表达式中某些匹配内容是用括号“()”包含起来的,那么re-find函数不仅会匹配整个正则表达式,还会返回满足括号内正则表达式的内容,会对括号依次递归返回,最后返回一个序列:

;;;;匹配内容第一个字母加了括号,所以会返回对第一个字母的匹配
(re-find #"([a-e])\d*" "whe12343ywe123weh")
;=> ["e12343" "e"]

;;;;匹配内容\d加了括号,这时返回*满足条件的最后一个数字
(re-find #"[a-e](\d)*" "whe12343ywe123weh")
;=> ["e12343" "3"]

;;;;对两处都加了括号,因此结果会返回一个大小为3的字符串数组
(re-find #"([a-e])%(d)*" "whe12343ywe123weh")
;=> ["e12343" "e" "3"]

  clojure在调用re-find函数时,会自动识别是否存在(),如果存在括号,则返回字符串序列,否则返回单个字符串。
  当需要查找整个字符串中所有满足正则表达式条件的字符串时,可以将re-find函数与re-matcher函数搭配使用。
2. re-matcher函数:
  返回 一个java类的匹配器,re-find函数可以使用该匹配器,以此返回满足匹配条件的所有字符串:

;;;;定义一个被匹配的字符串
(def phone-number "672-345-456-3212")

;;;;定义一个re-matcher
(def matcher (re-matcher #"\d+" phone-number))

;;;;连续调用re-find函数可以返回phone-number中所有满足条件的内容
(re-find matcher)
;=>"672"
(re-find matcher)
;=>"345"
(re-find matcher)
;=>"456"
(re-find matcher)
;=>"3212"

;; 最后找不到满足条件的内容,会返回nil
(re-find matcher)
;=>nil

3. re-seq函数:

  这个函数将所有满足正则表达式的内容以序列的形式返回,把re-matcher与re-find函数运行的结果暴露一个不可变的序列,可以减少代码膨胀,是序列的典型应用:

;;;;re-seq会把所有满足条件的字符串以序列的形式返回
(re-seq #"[a-e]\d*" "whe12343ywa1299dhjd")
;=> ("e12343" "a1299" "d" "d")

;;;;如果遇到()嵌套,会返回一个二维数组
(re-seq #"([a-e])\d*" "whe12343ywa1299dhjd")
=> (["e12343" "e"] ["a1299" "a"] ["d" "d"] ["d" "d"])

4. replace函数:
  replace函数是clojure.string库下的函数,可以将一个字符串中满足a的内容替换成b,简单情况下,replace可以替换普通的字符串:

(clojure.string/replace "The color is red,this color is red" "red" "blue")
;=> "The color is blue,this color is blue"

  如果给replace函数的第二个参数传递一个正则表达式,那么该字符中所有满足正则表达式模式的内容都会被第三个参数替换:

;;;;所有满足前两个字符是字母,第三个字符是数字的内容都被xxx所替换
(clojure.string/replace "fabulous fodder foo1 foo3d" #"oo\d" "xxx")
;=> "fabulous fodder fxxx fxxxd"

  更神奇的是,replace函数第三个参数可以接收一个函数,用于更改被替换的内容:

;;;;用匿名函数将原来的原因字母扩展成连续两个元音字母
(clojure.string/replace "The color is red." #"[aeiou]" (fn [x] (str x x)))
;=> "Thee cooloor iis reed."

5. replace-first函数:
 &emsp该函数与replace函数实现形式基本一致,只不过replace-first函数只替换第一个满足条件的值:

(clojure.string/replace-first "The color is red." #"[aeiou]" (fn [x] (str x x)))
;=> "Thee color is red."

6. split函数:
  该函数将字符串分成一组子串,split函数接收两个参数,一个是待切分的字符串,一个是切分字符串的依据,该依据可以是普通的字符串,也可以是正则表达式:

;;;;以空格切分字符串
(clojure.string/split "Clojure is awesome!" #" ")
;=> ["Clojure" "is" "awesome!"]

;;;;以数字切分字符串
(clojure.string/split "q1w2e3r4t455y6u7i8o9p0" #"\d+")
;=> ["q" "w" "e" "r" "t" "y" "u" "i" "o" "p"]

7. re-groups函数:
  接受一个matcher,返回和这个matcher相匹配的最近一次发现的集合。常与re-find、re-matcher函数结合使用,因为re-find函数依次访问与matcher相匹配的内容,而re-groups则可以获取re-find函数最近一次匹配的内容。如果没有嵌套匹配的集合,则返回一个完全匹配的字符串。如果有嵌套集合,则返回vector集合,第一个元素是完全匹配的(非嵌套):

;;;;定义一个需要匹配的字符串
(def phone-number "672-345-456-3212")
;=> #'insight.main/phone-number

;;;;定义一个matcher
(def matcher (re-matcher #"((\d+)-(\d+))" phone-number))
;=> #'insight.main/matcher

;;;;在没有使用re-find之前调用re-groups会抛出异常,因为找不到最近一次匹配
(re-groups matcher)
;IllegalStateException No match found  java.util.regex.Matcher.group (Matcher.java:485)

;;;;使用re-find函数以后,就可以用re-groups获取最近一次的匹配了
(re-find matcher)
;=> ["672-345" "672-345" "672" "345"]
(re-groups matcher)
;=> ["672-345" "672-345" "672" "345"]

注意:以上的函数:split/replace/replace-first三个函数都是clojure.string库中的函数,这三个函数只针对字符串进行操作。但是在eplace函数与split函数在clojure.core中也存在同名函数,它们的含义与以上介绍的函数不一样。

  • clojure.core/replace函数:
    该函数第一个参数是一个是map或者vector,第二个参数是一个vector/list,根据第二个参数中的key去获取第一个参数中的value,如果对应的value不存在,则返回key:
;;;;获取序列[10 9 8 7 6]中对应序号为0,2,4的内容
(replace [10 9 8 7 6] [0 2 4])
;=> [10 8 6]

;;;;获取序列[10 9 8 7 6]中对应序号为0,2,4,15的内容,因为序号15不存在,直接返回15
(replace [10 9 8 7 6] [0 2 4 15])
;=> [10 8 6 15]

;;;;获取map中key为4,3,4,4,5,6,2的value,若不存在则返回key
(replace {2 :two, 4 :four} [4 2 3 4 5 6 2])
;=> [:four :two 3 :four 5 6 :two]
  • clojure.core.async/split函数:
    该函数主要用于异步通信时,对异步返回的结果的多个内容根据某个谓词函数分为两类,其具体函数文档网址如下:https://clojuredocs.org/clojure.core.async/split,这里就不介绍了。

更新记录:
2016年7月9日:第一次书写
2016年7月11日:增加re-groups函数

猜你喜欢

转载自blog.csdn.net/zdplife/article/details/51868499