当前位置: 首页 > news >正文

刘亦菲生日当天,引发了我对正则的思考

前两天从网上采集到一条短视频数据(刷短视频),发现六公主连排5部刘亦菲主演的电影!甚是震惊,太有牌面了,看了一下日子是8月25号,嗷,原来当天是刘亦菲的生日。巧了,正好也是我家柴犬旺财的3岁生日😀。

言归正传,我们看到这条数据的

标题:#刘亦菲35岁生日获央视独宠# 神仙姐姐生日快乐!

为了分析数据,我们需要获取数据中所提到的话题#刘亦菲35岁生日获央视独宠#。提问:你能想到几种实现方式呢?欢迎评论区留言。

正则

想必细心看标题的朋友一定会猜到本文的主人公——正则,这玩意优点是写起来快,但缺点也显而易见,性能差,跟批处理一个德性,反人类的难记,长时间不用,每次都要重新学习,日常开发中也就偶尔写工具用一下。因此,我们只需要把常用的正则理解透就可以了,不要有心理包袱,看完本文,大部分的正则使用场景就可以活学活用。

场景一:匹配两个#之间的字符串

现在我们把需求转换成实现思路,想要获取上述数据中的话题,其实就是匹配两个#之间的文本内容,show code:

正则表达式#.*?#

    public static void main(String[] args) {
        String title = "#刘亦菲35岁生日获央视独宠# 神仙姐姐生日快乐!";
        Pattern p = Pattern.compile("(#.*?#)");
        Matcher m = p.matcher(title);
        while (m.find()) {
            String group = m.group(0);
            System.out.println("话题:" + group);
        }
    }

输出

话题:#刘亦菲35岁生日获央视独宠#

可以看出,输出的结果就是该条数据的话题,给大家分析一下这个正则表达式: .表示任意字符,?平时表示匹配0个或者多个,此时它表示不贪婪,那什么是贪婪呢?

说到贪婪,那就不得不提这两个限定符:*+ ,它们两个就是贪婪的!*表示匹配0个或者多个,+表示匹配至少一个,可以发现它们的共性:都会尽可能匹配更多。但,只要紧跟在它们的后面加上一个 ? ,让他们扪心自问,就可以实现非贪婪,即最小匹配。比如,我们在标题上再加一个#,此时标题变为#刘亦菲35岁生日获央视独宠## 神仙姐姐生日快乐!,然后正则表达式我们不使用?,此时,运行代码后输出结果为:

话题:#刘亦菲35岁生日获央视独宠##

比较两次的执行结果,我们会发现输出结果多了一#,这样就很贪婪,违背了我们的初衷,这就是?的妙用。

场景二:只匹配#开头的字符串

我们知道不同平台的话题格式是不一样的,比如抖音,它的话题形式就与微博不同,只是#开头,并没有成对的#与其呼应:

标题:#刘亦菲35岁生日获央视独宠 神仙姐姐生日快乐!

如果是这种形式的话题,爱动脑筋的朋友就会发现无非就是将后面的#变为一个空格或者多个空格呗。没错,我们可以使用

正则表达式#.*?\\s+

    public static void main(String[] args) {
        String title = "#刘亦菲35岁生日获央视独宠  神仙姐姐生日快乐!";
        Pattern p = Pattern.compile("(#.*?\\s+)");
        Matcher m = p.matcher(title);
        while (m.find()) {
            String group = m.group(0);
            System.out.println("话题:" + group);
        }
    }

输出

话题:#刘亦菲35岁生日获央视独宠 

Tips\s 表示匹配所有空白符,它不仅仅可以匹配空格,还可以匹配换行等空白字符,如果再加上+,组合起来就表示甭管几个空白字符,统统all in。

不过,不要高兴得太早,心细的小明还发现话题可能会存在文末的情况:

标题:神仙姐姐生日快乐!#刘亦菲35岁生日获央视独宠

此时是没有空白字符结束的,上面的正则就不满足这种情况。那如何是好?小明当时就想到了两个方案:

  • 方案一:不管话题在不在文末,我们在匹配之前全部给标题追加一个空白字符,这样就可以人为干预,巧妙地避开了这种情况,曲线救国,便于正则匹配
  • 方案二:使用正则表达式#.*?$

Tips:方案二中的$ 是用来匹配输入字符串的结尾位置,组合起来就表示匹配#开头,一直到句末的话题。

进阶

前面两种场景我们虽然获取到了两个#之间或者#开头的内容,实现了需求,但是匹配的结果还是会带上#,贪婪的小明不满足现状(产品强制要求),可不可以不带呢? 当然可以了!小明又想到了两个方案:

  • 方案一:得到匹配的话题后,再二次文本处理去掉#
  • 方案二:使用正则表达式?<=?=一步到位,直接去除#

使用方法

  • (?<=exp2)exp1:表示匹配 exp2 后面的 exp1
  • exp1(?=exp2):表示匹配 exp2 前面的 exp1 那结合以上我们实际使用的所有场景,最终这个理想的正则表达式就正式出炉(好热):((?<=#).*?(?=#|\s+)) (好热) 反应慢的朋友,可以慢点理解,我们先运行试一下(不自信):
    public static void main(String[] args) {
        String title = "#刘亦菲# #神仙姐姐 #生日快乐# #刘亦菲35岁生日获央视独宠";
        Pattern p = Pattern.compile("((?<=#).*?(?=#|\\s+|$))");
        Matcher m = p.matcher(title);
        while (m.find()) {
            String group = m.group(0);
            System.out.println("话题:" + group);
        }
    }

输出

话题:刘亦菲
话题:
话题:神仙姐姐
话题:生日快乐
话题:
话题:刘亦菲35岁生日获央视独宠

Tips:正则表达式中的|表示或,即多项之间的一个选择,就像今天你看完本文,感觉不错的话, 必须做出(关注|点赞|星标)其中的一个选择! 从代码的输出结果我们可以看出,目前的正则是经得住实际考验的。但是唯一美中不足的是,会有空字符串的情况出现(产品不同意)。 这该如何是好? 目前小明的解决方案是,拿到匹配结果时,过滤掉空字符串。能解决问题的办法就是好办法。不过,肯定有更完美的表达式可以实现这个需求,此处抛砖引玉,期待你在评论区分享!

常用的正则表达式分享

  • 微信号(并不能帮你要到男神|女神的微信号)
^[a-zA-Z][a-zA-Z\d_-]{5,19}$

未完待续……

相关文章:

  • Tomcat - 从源码阅读中分析核心组件
  • Android Glide应用中遇到问题
  • 个人云服务的搭建(折腾)之旅
  • 浅谈js中的深拷贝和浅拷贝
  • Hbase-3-4-Hbase读写数据流程
  • Oracle——常用的几种函数(含案例)
  • 【Linux】多线程 —— 线程概念 | 线程控制
  • windows10创建ssh git gitee使用公钥私钥【自留收藏】
  • 微信搜题接口API功能
  • YBTOJ 树状数组 二进制
  • 无胁科技-TVD每日漏洞情报-2022-8-30
  • Java8 特性(一):函数、Lambok、Stream
  • 定时器(Quartz)
  • 神经网络实现线性回归,神经网络是回归算法吗
  • MFC调用VLC库播放中文路径导致崩溃的问题
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • CSS 三角实现
  • IndexedDB
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • Next.js之基础概念(二)
  • python_bomb----数据类型总结
  • Redis 懒删除(lazy free)简史
  • Redis在Web项目中的应用与实践
  • spark本地环境的搭建到运行第一个spark程序
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 讲清楚之javascript作用域
  • 漂亮刷新控件-iOS
  • 王永庆:技术创新改变教育未来
  • 微信开放平台全网发布【失败】的几点排查方法
  • 我建了一个叫Hello World的项目
  • 译有关态射的一切
  • 阿里云ACE认证学习知识点梳理
  • #DBA杂记1
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (正则)提取页面里的img标签
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .jks文件(JAVA KeyStore)
  • .md即markdown文件的基本常用编写语法
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET 中创建支持集合初始化器的类型
  • .NET基础篇——反射的奥妙
  • .NET委托:一个关于C#的睡前故事
  • /var/spool/postfix/maildrop 下有大量文件
  • :O)修改linux硬件时间
  • @DependsOn:解析 Spring 中的依赖关系之艺术
  • @基于大模型的旅游路线推荐方案
  • [1181]linux两台服务器之间传输文件和文件夹
  • [383] 赎金信 js
  • [bzoj1324]Exca王者之剑_最小割