😝 这次一定 | "学废" 正则表达式 🙋‍♂️(中)

简介: 正则表达式 → 没有一个开发仔会对这个词陌生吧?没印象的话,想想你是如何 判断身份证、手机号码是否合法的 ?Tips:本节代码示例基于Python的re库编写,虽大部分编程语言的正则库都是师从 Perl语言,语法基本一样,但也可能略有差异~

③ 数量


只使用上述元字符,只能匹配单个字符,想匹配多个字符还得搭配下述元字符:


  • | → 逻辑或操作符,比如"ab"和"ac"都想匹配到,可以用这样的正则:"ab|c"
  • * → 前一个字符(子表达式) 出现0次或无限次,即可有可无
  • + → 前一个字符(子表达式) 出现1次或无限次,即最少一次
  • ? → 前一个字符(子表达式) 出现0次或1次,即要么不出现,要么只出现一次
  • {m} → 前一个字符(子表达式) 出现m次;
  • {m,} → 前一个字符(子表达式) 至少出现m次;
  • {m,n} → 前一个字符(子表达式) 出现m到n次;


Tips:尽量使用*+?,因为做了优化,相比起{m}{m,}{m,n}速度更快。


④ 集合与区间


当我们想匹配多个字符中的一个,比如匹配26个小写字母,得怎么写?下面这样吗?


a|b|c|d|e|f|g|h|...太长省略


如果还得匹配26个大写字母呢?拼接一堆或操作符,繁琐得一匹,可以使用 集合与区间元字符 来简化,有下面这些:


  • [] → 匹配字符集合[]中列举的字符,如:[abc],就是匹配abc中的一个字符;
  • [^] → 匹配不在字符集合[]中列举的字符,如:[^abc],就是匹配不在abc中的字符;
  • - → 定义一个区间,或者说匹配一个范围,如:[a-z] 就是匹配26个小写字母中的一个;


⑤ 位置边界


在查找过程中,有时我们还得限制查询的位置,比如只想在单词的开头或结尾查找字符,可以用下面这些元字符:


  • ^ → 匹配一行的开始,多行模式能识别\n;
  • $ → 匹配一行的结尾,多行模式能识别\n;
  • \A → 匹配字符串开头,单行模式效果同^,多行模式不能识别\n;
  • \Z → 匹配字符串结尾,单行模式效果同$,多行模式不能识别\n;
  • \b → 匹配单词边界,即单词和空格间的位置,如:er\b 可以匹配never中的er,却不能匹配verb中的er;
  • \B → 匹配非单词边界;
  • < → 匹配单词开头;
  • > → 匹配单词结尾;


0x3、简单练手 → 手撕验证手机号码格式的正则


光说不练假把式,光练不说傻把式,又练又说真把式,欲速则不达,学完基础语法,先写个例子练练手,找找感觉~


如题,手撕验证手机号码格式的正则,怎么玩?


可以把一个正常的手机号码拆成三个部分写正则,最后再拼起来~


① 号码前缀


要么要么,要么有的话只有一个,用 ?,接着取值的话可能是下面这三种:


  • 0 (长途)
  • 86 (天朝国际区号)
  • 17951 (国际电话)


不难写出这样的正则:(0|86|17951)?,圆括号代表子表达式,你可以先理解成分组,等下会详细讲~


② 1xx


接着到1xx,有这几种:13x、14x、15x、17x、18x,然后后面的x对应的取值范围是不一样的:


  • 13x:0123456789
  • 14x:579
  • 15x:012356789
  • 17x:01678
  • 18x:0123456789


看着很复杂?其实不然,用好 |集合与区间元字符 就好,根据规则不难写出这样的正则:


(13[0-9]|14[579]|15[0-35-9]|17[01678]|18[0-9])


③ 剩下的8个数字


数字就行,想都不用想直接写出:(\d{8}),最后拼接下三段正则:


(0|86|17951)?(13[0-9]|14[579]|15[0-35-9]|17[01678]|18[0-9])(\d{8})


接着搜索引擎搜下 手机号码大全,随手点开一个站点,F12 → Source 输入上述正则查下看看:


网络异常,图片无法展示
|


可以,匹配到了,但是好像也匹配了一些奇怪的东西,比如上面的 921-xxx.html,简单,加上$匹配一行结束即可~


网络异常,图片无法展示
|


例子刷完了,简单吧!接着继续了解正则的高级语法~


0x4、高级语法


说是高级也不见得有多高级,只是得稍微动下脑子而已~


① 分组


就是使用一对 圆括号() 包裹 子表达式,它是构成高级正则表达式的基础。如果没用到后续的语法,分不分组其实是一样的~


② 反向引用


又称 回溯引用,指的是:模式的后面内容,引用前面已经匹配到的子字符串。有点懵?写个简单例子帮助理解,现在有这样一段字符串:


pineapple peach plum watermelon durian durian grape mango strawberry strawberry chestnut


想匹配两个连续相同的单词,可以这样写正则:


网络异常,图片无法展示
|


所以反向引用的语法就是:\第几个子字符串,反向引用在 替换字符串 的场景很常用。


替换时语法上有些许差异,一般使用 \g<第几个字符串> 来引用要被替换的字符串。以之前文章替换字符串部分内容为例~


网络异常,图片无法展示
|


Markdown语法的图片URL,被一个换行符\n分割成了两行,又不能全局替换\n,因为会影响其他文本的格式,只替换这种异常的图片URL,利用反向引用就可以做到。


error_pic_pattern_n = re.compile(r'(http.*?)(\n)(.*?\.\w+\))', re.M)
# 就是划分成了三个分组(子表达式),然后把1、3分组拼接结果作为替换结果
new_content = error_pic_pattern_n.sub(r"\g<1>\g<3>", new_content)


反向引用,就这?就拿子表达式的匹配结果乱玩而已?是的,就是这么简单~


另外,如果不想子表达式被引用,可以使用 非捕获正则 → (?:子表达式),这样玩还可以避免浪费内存~


③ 前/后向查找


又称 前/后向段言顺序/逆序环视前瞻后顾 等,又是些牛马专业名词?


不急,写个简单例子帮助理解它得玩法,打开苹果官网 识别您的 iPhone 机型,现在有个这样的需求:


想看下iphone 11、12、13都有哪些机型,要求写个正则筛一波


先写个能提取所有机型的正则吧:


<h2>iPhone .*?</h2>


网络异常,图片无法展示
|


可以拿到机型,但是原需求只想筛11、12、13的机型,什么XS、XR的不感兴趣,这个时候就可以上 向前肯定断言(?=) 了。改完后的正则:


<h2>iPhone (?=13|12|11).*?</h2>


网络异常,图片无法展示
|


可以,除了11、12、13,其他型号的阿猫阿狗都没匹配到,不难看出 前向肯定断言(?=re) 在这里的作用就是:


先找到满足断言里 子表达式 → 13|12|11 的位置,然后在这个 位置往前 找匹配 <h2>iPhone 的字符串;


这个顺序很关键哈!!!先找断言里的子表达式,再找前面的表达式,这一点,很多教程都说得不清不楚!!


向前肯定断言的玩法了解了,其他三种断言也就一点就通了:


  • (?!re)前向否定断言,先匹配不满足re的位置,然后向前匹配;
  • (?<=re)后向肯定断言,先匹配满足re的位置,然后向后匹配;
  • (?<!re)后向否定断言,先匹配不满足re的位置,然后向后匹配;


读者可以自行试试下述例子加深理解:


# 前向否定断言,看11、12、13外的机型
<h2>iPhone (?!11|12|13).*?</h2>
# 后向肯定断言,看下有Plus系列的机型有哪些
<h2>iPhone .*?(?<=Plus)</h2>
# 向后否定断言,看下没Plus系列的机型有哪些
<h2>iPhone .*?(?<!Plus)</h2>


限于篇幅就不贴结果图了哈,再说两个个要注意的点哈:


  • ① 断言里的子表达式,不消耗字符!不会影响你外部正则表达式的匹配!!!
  • 前瞻后顾 在某些语言或环境下可能不支持,使用时要谨慎验证支持情况哈!!!


相关文章
|
算法 Python Perl
😝 这次一定 | "学废" 正则表达式 🙋‍♂️(下)
正则表达式 → 没有一个开发仔会对这个词陌生吧?没印象的话,想想你是如何 判断身份证、手机号码是否合法的 ?Tips:本节代码示例基于Python的re库编写,虽大部分编程语言的正则库都是师从 Perl语言,语法基本一样,但也可能略有差异~
166 0
|
Web App开发 数据可视化 搜索推荐
😝 这次一定 | "学废" 正则表达式 🙋‍♂️(上)
正则表达式 → 没有一个开发仔会对这个词陌生吧?没印象的话,想想你是如何 判断身份证、手机号码是否合法的 ?Tips:本节代码示例基于Python的re库编写,虽大部分编程语言的正则库都是师从 Perl语言,语法基本一样,但也可能略有差异~
191 0
|
1月前
|
Python
Python 内置正则表达式库re的使用
正则表达式是记录文本规则的代码,用于查找和处理符合特定规则的字符串。在Python中,常通过原生字符串`r&#39;string&#39;`表示。使用`re.compile()`创建正则对象,便于多次使用。匹配字符串有`match()`(从开头匹配)、`search()`(搜索首个匹配)和`findall()`(找所有匹配)。替换字符串用`sub()`,分割字符串则用`split()`。
40 3
|
24天前
|
数据库 Python
Python网络数据抓取(8):正则表达式
Python网络数据抓取(8):正则表达式
17 2
|
7天前
|
自然语言处理 JavaScript 前端开发
Python高级语法与正则表达式(二)
正则表达式描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
|
7天前
|
安全 算法 Python
Python高级语法与正则表达式(一)
Python提供了 with 语句的写法,既简单又安全。 文件操作的时候使用with语句可以自动调用关闭文件操作,即使出现异常也会自动关闭文件操作。
|
15天前
|
Python
Python使用正则表达式分割字符串
在Python中,你可以使用re模块的split()函数来根据正则表达式分割字符串。这个函数的工作原理类似于Python内置的str.split()方法,但它允许你使用正则表达式作为分隔符。
|
1天前
|
Python
Python正则表达式详解:掌握文本匹配的魔法
Python正则表达式详解:掌握文本匹配的魔法
|
1天前
|
Python
python re 正则表达式库的使用
python re 正则表达式库的使用
3 0
|
25天前
|
Python
Python中re模块的正则表达式
【6月更文挑战第2天】了解Python的re模块,它是处理正则表达式的核心工具。正则表达式用于在文本中查找特定模式。本文讨论了re模块的用法和技巧,包括导入模块、匹配、分组、替换文本、编译正则表达式以及使用预定义字符类、量词、锚点等高级功能。通过实例展示了如何在Python中执行这些操作,帮助提升文本处理能力。掌握这些技巧将使你更有效地利用正则表达式解决字符串处理问题。
16 2