跳至主要內容

Python之正则表达式细讲

PaperDragon...大约 12 分钟

Python之正则表达式细讲

一、行定位符

行定位符就是用来描述字符串的边界,“^” 表示行的开始,“$” 表示行的结尾。比如:

^Ha

该表达式表示要匹配字符串的开头位置是 Ha,如 “Hangzhou is a very beautiful city” 可以匹配,而 “Your words are very funny, Ha” 则不匹配。但如果使用:

Ha$

后者可以匹配而前者不能匹配。如果要匹配的字符串可以出现在字符串的任意部分,那么可以写成下面的格式,这样两个字符串都能匹配上。

Ha

二、元字符

除了前面介绍的 “^” 和 “$” 外,正则表达式里还有更多的元字符,例如下面的正则表达式中就应用了元字符 “\b” 和 “\w”。

\ban\w*\b

上面的正则表达式用于匹配以字母 an 开头的字符串,先从字符串的开头 an 处开始匹配,接着是任意数量的字母或数字(\w*)。该表达式可以匹配 “anaconda” 和 “and246”,但不能与 “abandon” 匹配。更多常见元字符如下表所示:

元字符说明举例
.匹配除换行符以外的任意字符. 可以匹配 “acd\n8R\t” 中的 a、c、d、8、R、\t
\w匹配字母、数字、下划线或汉字\w 可以匹配 “miO次9\nqw” 中的 “m、i、O、次、9、q、w”,但不能匹配 \n
\W匹配除字母、数字、下划线或汉字以外的字符\W 可以匹配 “92d\nsc” 中的 \n,但不能匹配 “9、2、d、s、c”
\s匹配单个的空白符(包括 Tab 键和换行符)\s 可以匹配 “c\t8B” 中的 \t
\S匹配除单个空白符(包括 Tab 键和换行符)以外的所有字符\S 可以匹配 “字we2\t90” 中的 “字、w、e、2、9、0”
\b匹配单词的开始或结束,单词的分解符通常是空格,标点符号或者换行在 “there were deserts where” 字符串中,\bw 与 were 中的 w 相匹配,但与 where 中的 w 不匹配
\d匹配数字\d 可以与 “dg34&” 中的 3、4 匹配

三、限定符

在上面例子中,使用(\w*)可以匹配任意数量的字母或数字。但如果想要匹配指定数量的数字,该如何表示呢?

正则表达式为我们提供了限定符(指定数量的字符) 来实现该功能。如匹配 11 位电话号码可使用如下表达式:

^\d{11}$

常用的限定符如下表所示:

限定符说明举例
?匹配前面的字符 0 次或 1 次Pyth?on,该表达式可以匹配 Python 和 Pyton
+匹配前面的字符 1 次或多次Py+thon,该表达式可以匹配的范围从 Python 到 Pyy…thon
*匹配前面的字符 0 次或多次Pyt*hon,该表达式可以匹配的范围从 Pyhon 到 Pytt…hon
{n}匹配前面的字符 n 次Pytho{3}n,该表达式只匹配 Pythooon
{n,}匹配前面的字符至少 n 次Pytho{3,}n,该表达式可以匹配的范围从 Pythooon 到 Pythooo…n
{n,m}匹配前面的字符最少 n 次,最多 m 次P{1,3}ython,该表达式可以匹配 Python、PPython、PPPython

四、字符类

正则表达式查找数字和字母是很简单的,因为已经有了对应这些字符集合的元字符(如 “\d”、“\w”),但是如果要匹配没有预定义元字符的字符集合(比如只匹配元音字母a,e,i,o,u),应该怎么办?   很简单,只需要在方括号里列出它们就行了,像 [aeiou] 可以匹配任何一个英文元音字母,[.?!] 匹配标点符号(“.”,“?”,“!”),也可以轻松的指定一个范围,像 “[0-9]” 代表的含义与 “\d” 就是完全一致的:代表一位数字。同理,“[a-z0-9A-Z_]” 完全等同于 “\w”(如果只考虑英文的话)。

五、排除字符

在上面的字符类中列出的匹配符合指定字符集合的字符串。现在反过来,匹配不符合指定字符集合的字符串。正则表达式提供了 “^” 字符。这个元字符在上面出现过,表示行的开始。而这里将会放到方括号中,表示排除的意思。例如:

[^a-zA-Z]

该表达式用于匹配一个不是字母的字符。

六、选择字符

试想一下,如何匹配身份证号码?首先需要了解一下身份证号码的规则。身份证号码长度为 18 位,前 17 位为数字,最后一位是校验位,可能为数字或字符 X。   在上面的描述中,包含着条件选择的逻辑,这就需要使用选择字符(|)来实现。该字符可以理解为 “或”,匹配身份证的表达式可以写成如下方式:

(\d{18}$)|(\d{17})(\d|X|x)$

该表达式的意思是匹配 18 位数字,或者 17 位数字和最后一位。最后一位可以是数字,也可以是 X 或者 x。

七、转义字符

正则表达式中的转义字符(\)和 Python 中的大同小异,可以将字符本身的含义转成特定的含义,如果是特殊字符(比如 “.” “?” “\” 等)则转变为普通的字符。举一个 IP 地址的实例,用正则表达式匹配诸如 “127.0.0.1” 格式的 IP 地址。如果直接使用点字符,格式为:

[1-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}

这显然不对,因为 “.” 可以匹配一个任意字符。这时,不仅是127.0.0.1 这样的 IP,连 127a0b0c1 这样的字符串也会被匹配出来。所以在使用 “.” 时,需要使用转义字符(\)。修改后上面的正则表达式格式为:

[1-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

说明括号在正则表达式中也算是一个元字符。

八、分组

通过上面的选择字符板块,大家对小括号的作用有了一定了解。小括号字符的第一个作用就是可以改变限定符的作用范围,如 “|” “*” “^” 等。例如下面的表达式中包含小括号。

(fruit|food)s

这个表达式的意思是匹配单词 fruits 或 foods,如果不使用小括号,那么就变成了匹配单词 fruit 和 foods 了。   小括号的第二个作用是分组,也就是子表达式。如 ([a-z]{1,3}){3},就是对分组 ([a-z]{1,3}) 进行重复操作。

九、正则表达式语法

在Python中使用正则表达式时,是将其作为模式字符串使用的。例如,将匹配不是字母的一个字符的正则表达式表示为模式字符串,可以使用下面的代码:

'[^a-zA-Z]'

而如果将匹配以字母 g 开头的单词的正则表达式转换为模式字符串,则不能直接在其两侧添加引号定界符,例如,下面的代码是不正确的。

'\bg\w*\b'

而是需要将其中的 “\” 进行转义,转换后的结果为:

'\\bg\\w*\\b'

由于模式字符串中可能包括大量的特殊字符和反斜杠,所以需要写为原生字符串,即在模式字符串前加 r 或 R。例如,上面的模式字符串采用原生字符串表示为:

r'\bg\w*\b'

r'\bg\w*\b'

🌱 说明:在编写模式字符串时,并不是所有的反斜杠都需要进行转换,没有特殊意义的就不用转。

常用正则表达式

方式表达式
[火车车次][GCDZTSPKXLY1-9]\d{1,4}
[手机机身码(IMEI)]\d{15,17}
[必须带端口号的网址](https?:\/\/)?([\da-z\.-]+)\.([a-z]{2,6})(:\d{1,5})([\/\w\.-]*)*\/?
[网址(支持端口和参数)](https?:\/\/)?([\da-z\.-]+)\.([a-z]{2,6})(:\d{1,5})?([\/\w\.-]*)*\/?(#[\S]+)?
[统一社会信用代码][0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}
[统一社会信用代码(宽松匹配)(15位/18位/20位数字/字母)]`(([0-9A-Za-z]{15})
[迅雷链接]thunderx?:\/\/[a-zA-Z\d]+=
[ed2k链接(宽松匹配)]ed2k:\/\/|file|.+|\/
[磁力链接(宽松匹配)]magnet:\?xt=urn:btih:[0-9a-fA-F]{40,}.*
[子网掩码]`(?:\d{1,2}
[linux"隐藏文件"路径]\/(?:[^/]+\/)*\.[^/]*/
[linux文件夹路径]\/(?:[^/]+\/)*
[linux文件路径]\/(?:[^/]+\/)*[^/]+
[window文件夹路径][a-zA-Z]:\\(?:\w+\\?)*
[window下文件路径][a-zA-Z]:\\(?:\w+\\)*\w+\.\w+
[股票代码(A股)]`(s[hz]
[html注释]<!--[\s\S]*?-->
[md5格式(32位)]`([a-f\d]{32}
[GUID/UUID][a-f\d]{4}(?:[a-f\d]{4}-){4}[a-f\d]{12}
[版本号格式必须为X.Y.Z]\d+(?:\.\d+){2}
[视频链接地址]`https?://(.+/)+.+(.(swf
[图片链接地址]`https?://(.+/)+.+(.(gif
[24小时制时间[HH:mm:ss]]`(?:[01]\d
[12小时制时间[hh:mm:ss]]`(?:1[0-2]
[base64格式]`^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==
[数字/货币金额[支持负数,千分位分隔符]]-?\d+(,\d{3})*(\.\d{1,2})?
[银行卡号10到30位, 覆盖对公/私账户][1-9]\d{9,29}
[中文姓名](?:[\u4e00-\u9fa5·]{2,16})
[英文姓名][a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]
[车牌号(新能源)]`[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z](?😦(\d{5}[A-HJK])
[车牌号(非新能源)][京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]
[车牌号(新能源+非新能源)][京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]
[手机号中国(严谨)]`(?😦?:+
[手机号中国(宽松),13,14,15,16,17,18,19开头即可]`(?😦?:+
[手机号中国(最宽松)]`(?😦?:+
[日期]`\d{1,4}(-)(1[0-2]
[邮箱][\w!#$%&'*+/=?^_{
[座机电话(国内)]`(?😦?:\d{3}-)?\d{8}
[身份证号(1代15位数字)]`[1-9]\d{7}(?:0\d
[18位身份证号,最后一位可能为数字或字符X]`[1-9]\d{5}(?:18
[身份证号,支持1/2代(15位/18位数字)]`(^\d{8}(0\d
[护照[包含香港、澳门]]`([EK]\d{8}
[帐号是否合法[字母开头,允许5-16字节,允许字母数字下划线组合]][a-zA-Z]\w{4,15}
[中文/汉字]`(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]
[小数]\d+\.\d+
[数字]\d{1,}
[html标签(宽松匹配)]<(\w+)[^>]*>(.*?<\/\1>)?
[qq号格式正确][1-9][0-9]{4,10}
[数字和字母组成][A-Za-z0-9]+
[英文字母][a-zA-Z]+
[小写英文字母组成][a-z]+
[大写英文字母][A-Z]+
[密码强度校验,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符]\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*
[用户名校验,4到16位[字母,数字,下划线,减号]][a-zA-Z0-9_-]{4,16}
[IPV4[:端口]]`((\d
[IPV6[:端口]]`(([0-9a-fA-F]{1,4}😃{7,7}[0-9a-fA-F]{1,4}
[16进制颜色]`#?([a-fA-F0-9]{6}
[微信号,6至20位,以字母开头,字母,数字,减号,下划线][a-zA-Z][-_a-zA-Z0-9]{5,19}
[邮政编码(中国)]`(0[1-7]
[中文和数字]`((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]
[不能包含字母][^A-Za-z]*
[java包名]([a-zA-Z_]\w*)+([.][a-zA-Z_]\w*)+
[mac地址]`((([a-f0-9]{2}😃{5})
[匹配连续重复的字符](.)\1+
[数字和英文字母组成,并且同时含有数字和英文字母](?=.*[a-zA-Z])(?=.*\d).+
[香港身份证][a-zA-Z]\d{6}\([\dA]\)
[澳门身份证]`[1
[台湾身份证][a-zA-Z][0-9]{9}
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3