一、前言
不着急讲述Regex,我们先看一个需求,统计某个字符或字符串在整个字符串中出现的次数,举例,字符串如下:
今天是2023年6月29日,北京,天气晴,与昨天不同的是,今天格外的热,也不知道明天会怎么样,是晴天还是阴天呢,具体得到明天才能知道了。
请统计“天”字出现的次数。
实现上边的功能,我相信大家,有很多种方式,下面也举例几种:
1、循环遍历
这是最常见,也是首先能想到的。
valcontent="今天是2023年6月29日,北京,天气晴,与昨天不同的是,今天格外的热,也不知道明天会怎么样,是晴天还是阴天呢,具体得到明天才能知道了。"varcount=0//遍历content.forEach { if ('天'==it) { count++//次数累加 } } print(count)
打印结果
8
2、Kotlin中count操作符
valcontent="今天是2023年6月29日,北京,天气晴,与昨天不同的是,今天格外的热,也不知道明天会怎么样,是晴天还是阴天呢,具体得到明天才能知道了。"valcount=content.count { ch->ch=='天' } print(count)
打印结果
8
3、Kotlin中的filter操作符
valcontent="今天是2023年6月29日,北京,天气晴,与昨天不同的是,今天格外的热,也不知道明天会怎么样,是晴天还是阴天呢,具体得到明天才能知道了。"valfilterContent=content.filter { ch->ch=='天' } print(filterContent.length)
打印结果
8
4、使用Java中的正则
valcontent="今天是2023年6月29日,北京,天气晴,与昨天不同的是,今天格外的热,也不知道明天会怎么样,是晴天还是阴天呢,具体得到明天才能知道了。"valpattern=Pattern.compile("天") valmatcher=pattern.matcher(content) varcount=0while (matcher.find()) { count++ } print(count)
打印结果
8
5、使用Regex对象
valcontent="今天是2023年6月29日,北京,天气晴,与昨天不同的是,今天格外的热,也不知道明天会怎么样,是晴天还是阴天呢,具体得到明天才能知道了。"valmatchResult=Regex("天").findAll(content) print(matchResult.count())
当然了还有很多的实现方式,我们暂且举这五种,看到第五种的Regex对象实现方式,有的铁子就问了,我丝毫没有发现Regex到底有什么可取之处啊,简单吗?与Kotlin的操作符相比,简直就是小巫见大巫,毫无优点可言,别慌啊铁子,如果只是简单的文本寻找,Regex绝对没有优势,毕竟,这只是它的一个引子,冰山一角的功能,我们慢慢拉开序幕~
二、Regex方法列举
通过以上的前言,我们大致知道了,原来Regex也可以实现查找的功能,无形当中,又多了一种选择方式,除此之外,它还有那些功能呢?
构造函数
我们先看一下基本的构造函数
方法 |
参数类型 |
概述 |
Regex(pattern: String) |
String |
要匹配的正则表达式模式。 |
Regex(pattern: String, option: RegexOption) |
String,RegexOption |
根据指定的模式字符串和指定的单个选项创建正则表达式。 |
Regex(pattern: String, options: Set) |
String,Set |
根据指定的模式字符串和指定的选项集创建正则表达式 |
对于一个参数的构造,没什么好说的,就是一个正则表达式,这也是我们最常用的,至于后面两个,相对使用的较少,不过我们还是简单的介绍一下:
RegexOption是一个枚举类型,具体类型如下:
参数 |
概述 |
IGNORE_CASE |
启用不区分大小写的匹配。大小写比较支持Unicode |
MULTILINE |
启用多行模式。 在多行模式中,表达式^和$分别在输入序列的行终止符或末尾之后或之前匹配。 |
LITERAL |
启用模式的文字分析。 输入序列中的元字符或转义序列将不会被赋予特殊含义。 |
UNIX_LINES |
启用Unix行模式。在这种模式下,只有'\n'被识别为行终止符。 |
COMMENTS |
允许在模式中使用空格和注释。 |
DOT_MATCHES_ALL |
启用表达式时的模式。匹配任何字符,包括行终止符。 |
CANON_EQ |
通过规范分解实现等价。 |
大家可以根据不同的情况,选择对应的参数即可,至于Set,无非就是多个RegexOption。
常见方法
了解完基本的构造,我们再来看下常用的方法:
方法 |
参数类型 |
概述 |
find(input: CharSequence, startIndex: Int = 0) |
CharSequence,Int |
寻找字符串中第一个匹配的MatchResult对象,默认从索引0开始。 |
findAll(input: CharSequence, startIndex: Int = 0) |
CharSequence,Int |
字符串中所有匹配的MatchResult序列,默认从索引0开始。 |
containsMatchIn(input: CharSequence) |
CharSequence |
如果包含输入的字符就返回true。 |
replace(input: CharSequence, replacement: String) |
CharSequence,String |
和String的replace类似,第一个是输入的目标字符,第二个是替换字符。 |
replaceFirst(input: CharSequence, replacement: String) |
CharSequence,String |
替换第一个查找到的字符 |
matches(input: CharSequence) |
CharSequence |
输入字符序列是否与正则表达式匹配 |
matchEntire(input: CharSequence) |
CharSequence |
用于匹配模式中的完整输入字符 |
三、Regex常见方法使用举例
在上篇文章《Android:这个需求搞懵了,产品说要实现富文本回显展示》中,不知道大家是否还有印象,对于富文本的截取,我们就采用了Regex,简简单单的就实现了富文本的内容获取,当然了也简单的介绍了部分的方法。下面,我们针对第二项中的各个方法,简单做个使用案例。
1、find
find,用于寻找第一次出现的结果,比如我们要寻找某个字符串中第一次出现的数字,如下举例:
valcontent="有这样一串数字2345,还有6789,以及012,我们如何只获取数字2345呢"valregex=Regex("\\d+") valmatchResult=regex.find(content) print(matchResult?.value)
打印结果
2345
2、findAll
findAll,顾名思义,就是寻找所有的结果,还是上面那个案例,我们改成findAll
valcontent="有这样一串数字2345,还有6789,以及012,我们如何只获取数字2345呢"valregex=Regex("\\d+") valmatchResult=regex.findAll(content) matchResult.forEach { println(it.value) }
打印结果
2345 6789 012 2345
还有一个典型的案例,就是富文本标签的截取,这个在上篇文章举例过了,大家可以看上篇文章。
3、containsMatchIn
用于判断是否包含某个字符,和String的使用方式类似:
valcontent="二流小码农"valregex=Regex("农") valregex2=Regex("中") valisContains=regex.containsMatchIn(content) valisContains2=regex2.containsMatchIn(content) println(isContains) println(isContains2)
打印结果
true false
4、replace
用于替换字符串中的相关内容:
valcontent="二流小码农"valregex=Regex("二") valreplaceContent=regex.replace(content,"一") println(replaceContent)
打印结果
一流小码农
5、replaceFirst
用于替换字符串中第一次相符合的内容:
valcontent="有这样一串数字2345,还有6789,以及012,我们如何只获取数字2345呢"valregex=Regex("\\d+") //把第一次出现的数字替换为字母abcdvalreplaceContent=regex.replaceFirst(content,"abcd") println(replaceContent)
打印结果
有这样一串数字abcd,还有6789,以及012,我们如何只获取数字2345呢
6、matches
用于输入的字符和目标内容是否匹配,比如用于邮箱的验证,手机号的验证等等情况:
//邮箱验证valcontent="11@qq.com"valcontent2="11@qq"valregex=Regex("[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+") valmatches=regex.matches(content) valmatches2=regex.matches(content2) println(matches) println(matches2)
打印结果
true false
7、matchEntire
用于匹配模式中的完整输入字符。
//匹配数字valregex=Regex("\\d+") valmatchResult=regex.matchEntire("二流小码农") valmatchResult2=regex.matchEntire("二流小码农666") valmatchResult3=regex.matchEntire("123456") println(matchResult?.value) println(matchResult2?.value) println(matchResult3?.value)
打印结果
null null 123456
四、总结
Regex相对于Java的Api来说,使用起来更加的简单,如果大家在非正则的功能使用时,比如寻找,替换,是否包含等等,完全可以使用字符串自带的功能即可,如果说要实现一些较为复杂的,比如邮箱的验证,手机号的验证等等,那么Regex绝对是你的首选。