正则表达式-如何从一个字符串中拿到特定内容

时间:2023-01-07 08:30:27

做Web开发时,经常需要从一个消息中去取得自己需要的字段信息,如果这个消息是Json或XML类型那很方便。但如果是个字符串呢,就像下面这样:

val str = “window.code=200;window.redirect_uri=\”wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=ARiFc26pwMtnUC2PBuJalkaS@qrticket_0&uuid=Yaw97YVBXQ==&lang=zh_CN&scan=1492838576\”;”

以下就是我做微信机器人时遇到的其中一种情况,需要从这个字符串中获取它的状态码(200)以及跳转的uri(wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=ARiFc26pwMtnUC2PBuJalkaS@qrticket_0&uuid=Yaw97YVBXQ==&lang=zh_CN&scan=1492838576)

起初我不了解正则表达式,看到它这么多的表达式类型,觉得这么多东西怎么记得住,即使花时间记住了过段时间也忘了。因此我一直没有深入的去理解正则表达式。我也一直以为正则表达式都是用来匹配某个模式串是否存在的,比如检测在”hello word”中是否有hello,毕竟很多的教程一上来都是说的这个。因此我起初对于这种在字符串获取特定的值,做法都是用sprit(),比如str.sprit(“;”)(0).sprit(“window.code=”)(1)来取到200,但是这种做法非常可怕,前提是要求字符串的格式永远不变,一旦格式发生些许变化,比如code和=之间多了一个空格,结果必然是一堆报错,最常见的就是数组越界。直到我后来看到了一篇讲正则表达式的文章正则表达式30分钟入门教程

发现我们可以用分组的方式很优雅的完成上面的工作。

先直接上代码,这里面用到了java工具包中的regex

import java.util.regex.Pattern
//编程语言用的Scala,java也类似,但这里重点讲的是正则表达式pattern
val str = "window.code=200;window.redirect_uri=\"wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=ARiFc26pwMtnUC2PBuJalkaS@qrticket_0&uuid=Yaw97YVBXQ==&lang=zh_CN&scan=1492838576\";"

val pattern = Pattern.compile(""".*window.code *= *(\d*).*window.redirect_uri *= *"(.*)".*""")
val matcher = pattern.matcher(str)
val boolean = matcher.matches()//true or false
val code = matcher.group(1)//200
val uri = matcher.group(2)//wx.qq.com.....

我们着重来看这个正则表达式

.*window.code *= *(\d*).*window.redirect_uri *= *”(.*)”.*

我们先将这个表达式简化一下

window.code=(\d*);window.redirect_uri=”(.*)”;

三个引号包括的字符串在Scala中也是表示字符串的意思,只是这里面的特殊字符不用加转义符“\”,这样看的比较直观。如果你的字符串用”“包括的话还是需要给特殊字符加上转义符。

这里\d*表示有零个或多个数字,.*表示有零个或多个字符,那为什么要用括号括起来呢?这里面就用到了分组,也就是下面的group。如果匹配成功,即boolean为true,括号中匹配的字符串就会存到group中,group顺序从1开始,有几对括号就有几个group,因此我们之后可以从group(1)中拿到200,在group(2)中拿到wx.qq.com/……&scan=1492838576

至于代码里更复杂的正则表达式,无非是加了一些特殊情况的判断,比如判断空格,或者前后有无多余字符等。

最重要的还是具体问题具体分析,这里只讲到了分组的功能,如何从一个字符串中拿到特定的内容,具体的更深入的正则表达式知识我们就可以去这篇教程(正则表达式30分钟入门教程)里找对应的表达式就好了