2023-05-26    2023-09-07    1020 字  3 分钟
OLs

很强大,也让人很头大…… 这只是一个精简的摘要,相信我,即使总结的再全面,一段时间之后,也需要借助参考手册,才能正确的使用它。

简介

正则表达式是什么?一个表达式,它定义了一种规则,用来匹配(符合规则的)字符串。

正则表达式本身也是用字符串表示的,如何表示呢?

:: 必须搭配例子一起食用,味道才好 😸 ……

简单匹配

1.精确匹配

在正则表达式中,如果直接给出字符,就是精确匹配。其他,还有:

元字符 说明
\d 匹配一个数字
\w 匹配一个字母或数字
\s 匹配一个空白符
. 匹配任意字符

当然,还有其他的,用的时候再查好了,反正是记不住的。

看一些示例:

  • '00\d' 可以匹配 '007' ,但无法匹配 +'00A'+ ;
  • '\d\d\d' 可以匹配 '010' ;
  • '\w\w\d' 可以匹配 'py3' ;
  • 'py.' 可以匹配 'pyc'、 'pyo'、 'py!' 等等。

2.匹配变长字符

元字符 说明
* 匹配任意个字符 (0 或 0+)
+ 匹配至少一个字符 (1 或 1+)
? 匹配 0 或 1 个字符
{n} 匹配 n 个字符
{m,n} 匹配 (m 到 n) 个字符

看一些示例:

  • \d{3} 表示匹配 3 个数字,如 '010' ;
  • \s+ 表示至少有一个空格,可以匹配 ' '、 ' ' 等;
  • \d{3,8} 表示匹配 3-8 个数字,如 '123'、 '12345'、 '12345678' 等。

如果要匹配 010-12345 这样的号码呢?由于 - 是特殊字符 ,在正则表达式中,要用 \ 转义,故上述的答案是 \d{3}\-\d{3-8} 。

如果,还不够,继续……

  1. 更精确的匹配

要做更精确的匹配,可以用 [] 表示范围,如 [0-9a-zA-Z\_] 可匹配一个数字、字母或者下划线。 其他,有:

元字符 说明
(A|B) 匹配 A 或 B
^ 表示行的开头
$ 表示行的结束

再来看一些示例:

  • [a-zA-Z\_][0-9a-zA-Z\_]* 可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串(看,这不就是 Python 的合法变量嘛);
  • (P|p)ython 可以匹配 'Python' 或者 'python' 。

进阶

  1. 分组

除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用 () 表示的就是要提取的分组(Group)。

比如, ^(\d{3})-(\d{3-8})$ 分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码。

1
2
3
4
5
6
7
m = re.match(r'^(\d{3})-(\d{3-8})$', '010-12345')
m.group(0)                      # '010-12345'
m.group(1)                      # '010'
m.group(2)                      # '12345'

# group(0) 永远是与整个正则表达式相匹配的字符串
# group(1)、group(2)... 表示第 1、2 个子串

5.贪婪匹配

需要注意的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符,加个 ? 可以切换成非贪婪匹配。

比如,我们要匹配出数字后面的 0 :

1
re.match(r'^(\d+)(0*)$', '102300').groups() # → ('102300', '')

由于 \d+ 默认采用贪婪匹配,直接把后面的 0 全部匹配了,结果 0* 只能匹配空字符串了。

必须让 \d+ 采用非贪婪匹配(也就是尽可能少的匹配),才能把后面的 0 匹配出来,如下:

1
re.match(r'^(\d+?)(0*)$', '102300').groups() # → ('1023', '00')

结语

以上内容主要来源于 廖雪峰老师的博客中关于正则表达式的章节 ,很短但很精致。如果,你想进一步练习的话,推荐: