scala|Scala:正则表达式详解

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的正则表达式的话例如:
    scala|Scala:正则表达式详解
    文章图片

    那么这样是可以调用的,没有问题
    得到的结果就是显示一个true:
    scala|Scala:正则表达式详解
    文章图片

    注意:如果正则表达式中存在一个group的话
    比如:
    scala|Scala:正则表达式详解
    文章图片

    结果:
    scala|Scala:正则表达式详解
    文章图片

    结果为true,没有问题
    现在将代码修改成如下形式:
    scala|Scala:正则表达式详解
    文章图片

    上面就是将match 中的 p2(_*)修改成了 p2(),这里的话,程序执行,编译不报错,但是p2Matches会得到false的结果。( 我的猜测就是正则表达式如果带有group的话,那么在match匹配中针对这个正则表达式,不传入的参数的话,就匹配不上,可能是在匹配的过程中会将这个字符串拆分成一个一个字符序列,然后将其与正则表达式相匹配)
  • 【scala|Scala:正则表达式详解】2.正则表达式中的group起别名
    创建一个新的带有group的正则匹配的表达式,可以为每个group起一个别名,代码示例如下:
    scala|Scala:正则表达式详解
    文章图片

    结果如下:
    scala|Scala:正则表达式详解
    文章图片

    上图打印出了group的名为year的对应的字符串表达式。
  • 3.含有groupmatch匹配中的case中含有带变量名的正则表达式
    在带有groupmach当中的正则表达式的括号里面可以给定一个变量的名,这样在进行模式匹配的过程中,如果有满足这个正则表达式的group的字符串里面。这个变量名就指代着这个字符串,然后就可以调用其中的一些方法了。代码案例如下:
    scala|Scala:正则表达式详解
    文章图片

    输出的结果如下:
    scala|Scala:正则表达式详解
    文章图片

    结果正如上所述,可以在模式匹配中抽取group中正则匹配出来的部分数据,做其它操作。
2.抽取已匹配的正则表达式中的部分内容(模式匹配表达式要写全) scala|Scala:正则表达式详解
文章图片

结果显示:
scala|Scala:正则表达式详解
文章图片

注意: 正则表达式中对应的提取位置需要有括号包裹,没有使用括号包裹的话,数据是无法提取出来的。
3.测试正则表达式是否被匹配 scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

这种做法就是单纯的检验正则表达式能否被匹配
4.抽取已匹配的正则表达式中的部分内容(模式匹配表达式不用写全) scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

注意:
此处之所以可以不用写全模式匹配中的表达式,是因为在dataRegex中添加了一个新的参数_*,因为这个参数的存在,可以检验整个正则表达式能否被匹配上带匹配数据。然后再从这个正则匹配表达式中抽取想要的数据。
另外应该注意到的一个点是:case dateRegex(year,_*)中里面的参数名字虽然叫做year,然而并不是说会有目的性的提取year这个变量,而应该总是提取第一个变量。
5.在给定字符串中查找指定模式的正则是否存在其中 scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

注意
这里面的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方法:匹配一个字符串中符合正则表达式的第一个字符串: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191229170404876.pngscala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

这段代码的功能是返回结果字符串第一个满足正则表达式匹配的字符串。
7.匹配一个字符串中符合正则表达式的字符串中第一个group的满足正则匹配的值 (这个标题是我自己写的,如果有更好的描述请在下面评论中给点建议啊,语文不是特别优秀,见谅)
scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

解释:
datas字符串中找到了满足正则表达式的第一个子字符串2004-01-20,然后从这个字符串中获取匹配正则表达式的第一个部分的字符串2004即:2004满足正则表达式(\d\d\d\d)
8.匹配一个字符串中符合正则表达式的字符串第一个group的所有满足值 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191229172951798.png
scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

这个代码与上面的代码不同的地方就是findFirstMatch修改成findAllMatch这样的话就可以获取所有满足正则匹配表达式的字符串,并将他们组成一个集合,然后在这个集合当中。将所有的满足正则表达式中第一部分的内容字符串提取出来组成一个集合,并将它们返回。
9.findAllIn:方法返回一个特殊的迭代器对象能够做最后的match查询 scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

解释:
也就是指调用了findAllIn函数之后,返回的迭代器的类型很特殊(在途中可以看到一个Regex.MatchIterator)的迭代器类型。接着利用这个迭代器进行一个过滤操作(过滤出满足正则匹配表达式中的第一部分的值小于1960的结果)
10.findAllIn()方法不会进行重叠匹配 scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

解释:
可以看到正则表达式num(\d+)这个意思是:匹配至少一个数字,程序的运行结果是:List(123)也就是说程序不会匹配得到类似List("123","23","3")这样的结果。
11.文本替换可以无条件执行,也可以作为当前匹配的函数执行: 原文:Text replacement can be performed unconditionally or as a function of the current match:
scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

例如这个操作,调用的是Regex实例里面的replaceAllIn()的方法,而一般我们平常写的都是String调用replaceAll()方法的方式是不同的(StringreplaceAll()的方法 str.replace("regex string","xxx str")
注意: 如果第二个参数是函数的话,那么作用又不一样了,请听我bb,例子如下:
scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

这里的执行细节如下:
1.第一第二行都是定义变量,没啥好说的。
2.第三行是获取一个本地月份(1月~12月)的数组。
里面的内容如下:
scala|Scala:正则表达式详解
文章图片

3.第四行则是,调用Regex类里面的repalceAll的方法了,先找到字符串变量dates里面符合,正则表达式date的一个个字符串("2004-01-20","1958-09-05",2010-10-06","2011-07-15"),然后输入到match模式匹配中(这里与之前不一样,上面的一个小节中,第二个参数传入的是一个正则表达式字符串,当前的第二个参数中传入的是一个模式匹配的表达式),抽取满足正则表达式的各个匹配部分的字符串,然后将它们排版打印输出。
模式匹配和正则表达式的匹配相比,创建时不重新应用正则表达式。在这个表达式reformatted(就是上面那张图里的变量),每个日期只匹配一次,但是它们可能是根据匹配的模式,应用一个正则表达式或者一个匹配模式产生结果。
就比如下面这个例子(上面的那个例子中,match里面模式匹配的表达式,接下来的例子中match就是正则的表达式)
scala|Scala:正则表达式详解
文章图片

结果:
scala|Scala:正则表达式详解
文章图片

对于这个结果,没啥好说的, 应该可以看得懂。
12.模式匹配中获取整个group的值 在含有match的模式匹配中获取含有整个group的值,代码示例如下:
scala|Scala:正则表达式详解
文章图片

结果为:
scala|Scala:正则表达式详解
文章图片

这个源码中的例子,我的理解是:关键点在于p4(all @ _*)这个地方,我对这个_*理解是和只上文所提到的一样,将匹配的字符串转化成字符序列,然后传入到p4()中。这个@符号的作用是:如果,这个正则表达式中的group被匹配上了,那么就将值赋于@之前的变量。最后得到的变量all是一个集合。调用mkstring方法转换成一个字符串,然后整个match匹配将值返回~
13.scala的字符的匹配 scala对字符的匹配,代码示例如下:
scala|Scala:正则表达式详解
文章图片

在上图中正则表达式(\p{Lower})是一个带有group的表达式(下面有红色的下划线就忽略掉吧,是idea的显示问题),所以在模式匹配当中,case后面的表达式里面都需要传入参数。而这一行case r() => true中没有传入参数,所以这个会在编译的时候报错scala.MatchError:c (of class java.lang.Character)的错误,如下所示:
scala|Scala:正则表达式详解
文章图片

注意:上面的代码将cat(0) match { case r() => true}注释掉就好了
14.字符匹配当中,如果正则表达式中有多个group只返回一个值 如下所示:
scala|Scala:正则表达式详解
文章图片

控制台上会打印一个true:
scala|Scala:正则表达式详解
文章图片

如果match的模式匹配中写成如下的形式:
scala|Scala:正则表达式详解
文章图片

结果显示为:
scala|Scala:正则表达式详解
文章图片

就说明没有匹配上。
15.匹配字符串中的子字符串 有的时候我们需要匹配给定的一个字符串中的子字符串。
比如我们要判断一个字符串:abcd1234中是否含有数字,我们可以这样实现:
scala|Scala:正则表达式详解
文章图片

结果为true 比较简单
以上内容就是我从ScalaRegex.scala文件中总结出来的,希望能对看到这篇文章的小伙伴们有一点点的帮助,如果你发现了我的文章里面有哪些地方写得不够好,请在评论下方留言。谢谢!

    推荐阅读