Scala 正则详解以及相关技巧总结
- 这篇博客的代码来源自Scala的Regex.scala文件,这里就不带大家看源码了,但是例子都是源码中的东西(可能稍微做了点修改)
文章目录
- Scala 正则详解以及相关技巧总结
- 1.关于正则匹配中的group
- 2.抽取已匹配的正则表达式中的部分内容(模式匹配表达式要写全)
- 3.测试正则表达式是否被匹配
- 4.抽取已匹配的正则表达式中的部分内容(模式匹配表达式不用写全)
- 5.在给定字符串中查找指定模式的正则是否存在其中
- 6.findFirstIn方法:匹配一个字符串中符合正则表达式的第一个字符串:
- 7.匹配一个字符串中符合正则表达式的字符串中第一个group的满足正则匹配的值
- 8.匹配一个字符串中符合正则表达式的字符串第一个group的所有满足值
- 9.findAllIn:方法返回一个特殊的迭代器对象能够做最后的match查询
- 10.findAllIn()方法不会进行重叠匹配
- 11.文本替换可以无条件执行,也可以作为当前匹配的函数执行:
- 12.模式匹配中获取整个group的值
- 13.scala的字符的匹配
- 14.字符匹配当中,如果正则表达式中有多个group只返回一个值
- 15.匹配字符串中的子字符串
1.关于正则匹配中的group
什么正则匹配中的group
?大致的意思就是如果一个正则表达式中有部分被括号包裹了例如(\d+)年
,那么这个正则表达式中就存在一个group
,(\d+)年(\d+)月
这样的话,里面就存在两个group
。好的,下面我要开始介绍一下其它的操作了,走起来
-
1.
group
的表达式的基本用法
如果是没有group
的正则表达式的话例如:
那么这样是可以调用的,没有问题
得到的结果就是显示一个true
:
注意:如果正则表达式中存在一个group
的话
比如:
结果:
结果为true
,没有问题
现在将代码修改成如下形式:
上面就是将match
中的p2(_*)
修改成了p2()
,这里的话,程序执行,编译不报错,但是p2Matches
会得到false
的结果。( 我的猜测就是正则表达式如果带有group
的话,那么在match
匹配中针对这个正则表达式,不传入的参数的话,就匹配不上,可能是在匹配的过程中会将这个字符串拆分成一个一个字符序列,然后将其与正则表达式相匹配) -
2.正则表达式中的group起别名
创建一个新的带有group
的正则匹配的表达式,可以为每个group
起一个别名,代码示例如下:
结果如下:
上图打印出了group
的名为year
的对应的字符串表达式。 -
3.含有
group
的match
匹配中的case
中含有带变量名的正则表达式
在带有group
的mach
当中的正则表达式的括号里面可以给定一个变量的名,这样在进行模式匹配的过程中,如果有满足这个正则表达式的group
的字符串里面。这个变量名就指代着这个字符串,然后就可以调用其中的一些方法了。代码案例如下:
输出的结果如下:
结果正如上所述,可以在模式匹配中抽取group
中正则匹配出来的部分数据,做其它操作。
2.抽取已匹配的正则表达式中的部分内容(模式匹配表达式要写全)
结果显示:
注意: 正则表达式中对应的提取位置需要有括号包裹,没有使用括号包裹的话,数据是无法提取出来的。
3.测试正则表达式是否被匹配
结果:
这种做法就是单纯的检验正则表达式能否被匹配
4.抽取已匹配的正则表达式中的部分内容(模式匹配表达式不用写全)
结果:
注意:
此处之所以可以不用写全模式匹配中的表达式,是因为在dataRegex
中添加了一个新的参数_*
,因为这个参数的存在,可以检验整个正则表达式能否被匹配上带匹配数据。然后再从这个正则匹配表达式中抽取想要的数据。
另外应该注意到的一个点是:case dateRegex(year,_*)
中里面的参数名字虽然叫做year
,然而并不是说会有目的性的提取year
这个变量,而应该总是提取第一个变量。
5.在给定字符串中查找指定模式的正则是否存在其中
结果:
注意
这里面的case embeddedDate()
中的三个参数要满足dataRegex
中括号里面的三个表达式,然后在待预测的字符串"Date: 2004-01-20 17:25:18 GMT (10 years, 28 weeks, 5 days, 17 hours and 51 minutes ago)"
中必须要存在,才能匹配上。
6.findFirstIn方法:匹配一个字符串中符合正则表达式的第一个字符串:

结果:
解释:
在datas
字符串中找到了满足正则表达式的第一个子字符串2004-01-20
,然后从这个字符串中获取匹配正则表达式的第一个部分的字符串2004
即:2004
满足正则表达式(\d\d\d\d)
8.匹配一个字符串中符合正则表达式的字符串第一个group的所有满足值
的迭代器类型。接着利用这个迭代器进行一个过滤操作(过滤出满足正则匹配表达式中的第一部分的值小于1960的结果)
10.findAllIn()方法不会进行重叠匹配
结果:
解释:
可以看到正则表达式num
是(\d+)
这个意思是:匹配至少一个数字,程序的运行结果是:List(123)
也就是说程序不会匹配得到类似List("123","23","3")
这样的结果。
11.文本替换可以无条件执行,也可以作为当前匹配的函数执行:
原文:Text replacement can be performed unconditionally or as a function of the current match:
结果:
例如这个操作,调用的是Regex
实例里面的replaceAllIn()
的方法,而一般我们平常写的都是String
调用replaceAll()
方法的方式是不同的(String
的replaceAll()
的方法 str.replace("regex string","xxx str")
注意: 如果第二个参数是函数的话,那么作用又不一样了,请听我bb,例子如下:
结果:
这里的执行细节如下:
1.第一第二行都是定义变量,没啥好说的。
2.第三行是获取一个本地月份(1月~12月)的数组。
里面的内容如下:
3.第四行则是,调用Regex
类里面的repalceAll
的方法了,先找到字符串变量dates
里面符合,正则表达式date
的一个个字符串("2004-01-20","1958-09-05",2010-10-06","2011-07-15")
,然后输入到match
模式匹配中(这里与之前不一样,上面的一个小节中,第二个参数传入的是一个正则表达式字符串,当前的第二个参数中传入的是一个模式匹配的表达式),抽取满足正则表达式的各个匹配部分的字符串,然后将它们排版打印输出。
模式匹配和正则表达式的匹配相比,创建时不重新应用正则表达式。在这个表达式reformatted
(就是上面那张图里的变量),每个日期只匹配一次,但是它们可能是根据匹配的模式,应用一个正则表达式或者一个匹配模式产生结果。
就比如下面这个例子(上面的那个例子中,match
里面模式匹配的表达式,接下来的例子中match
就是正则的表达式)
结果:
对于这个结果,没啥好说的, 应该可以看得懂。
12.模式匹配中获取整个group的值
在含有match
的模式匹配中获取含有整个group的值,代码示例如下:
结果为:
这个源码中的例子,我的理解是:关键点在于p4(all @ _*)
这个地方,我对这个_*
理解是和只上文所提到的一样,将匹配的字符串转化成字符序列,然后传入到p4()
中。这个@
符号的作用是:如果,这个正则表达式中的group
被匹配上了,那么就将值赋于@
之前的变量。最后得到的变量all
是一个集合。调用mkstring
方法转换成一个字符串,然后整个match
匹配将值返回~
13.scala的字符的匹配
scala对字符的匹配,代码示例如下:
在上图中正则表达式(\p{Lower})
是一个带有group
的表达式(下面有红色的下划线就忽略掉吧,是idea
的显示问题),所以在模式匹配当中,case
后面的表达式里面都需要传入参数。而这一行case r() => true
中没有传入参数,所以这个会在编译的时候报错scala.MatchError:c (of class java.lang.Character)
的错误,如下所示:
注意:上面的代码将cat(0) match { case r() => true}
注释掉就好了
14.字符匹配当中,如果正则表达式中有多个group只返回一个值
如下所示:
控制台上会打印一个true:
如果match
的模式匹配中写成如下的形式:
结果显示为:
就说明没有匹配上。
15.匹配字符串中的子字符串
有的时候我们需要匹配给定的一个字符串中的子字符串。
比如我们要判断一个字符串:abcd1234
中是否含有数字,我们可以这样实现:
结果为true 比较简单
以上内容就是我从Scala
的Regex.scala
文件中总结出来的,希望能对看到这篇文章的小伙伴们有一点点的帮助,如果你发现了我的文章里面有哪些地方写得不够好,请在评论下方留言。谢谢!