正则表达式基础

Python 正则表达式

正则表达式在处理字符串时具有很高的效率,特别是字符串比较长时,python中正则表达式是必须要掌握的内容,尤其是做数据处理时。

元字符

正则表达式中使用英文句点对换行符之外的任意字符进行匹配,但是注意一个句点只能匹配一个字符,比如’.ython’可以与’python’和’jython’都匹配,但是与’cpython’、’ython’等字符是不匹配的。句点可以与换行符之外的所有字符匹配,因此称为通配符。另外还有一些元字符:

  • \w 匹配字母或者数字或者下划线或汉字
  • \W 匹配任意不是字母、数字、下划线、汉字的字符等价于[^A-Za-z0-9_]
  • \s 匹配任务空白符,包括空格、制表符、换页符等
  • \S 匹配任意不是空白符的字符,等价于[]
  • \d 匹配数字
  • \D 匹配任意非数组的字符 [^0-9]
  • \b 匹配单词的开始或者结束
  • \B 匹配不是单词开头或者结束的位置

特殊字符转义

字符串中可能存在特殊字符,比如要匹配’python.org’这个字符串时,就不能直接使用’python.org’进行匹配,因为被匹配的字符串中存在特殊字符’.’,这个句点本身就是通配符,需要特殊处理,即要对其进行转义,在前面加上转义符号’\’,这样上面的例子就应该使用’python\.org’来匹配想要的字符串’python.org’。

细心的同学可能发现了这里用了两个’\’,这是应为这里的转义分两层,第一层是解释器的转义,第二层是python的re模块的转义,如果只写一个’\’,那么’.’就会被当做一个整体传递给re模块,这有可能会造成内容的丢失,因此需要写两个’\’。如果不想要写连个’\’,Python中可以这样做,r’python.org’,使用原字符串。

字符集

字符集匹配是使用一个方括号’[]’来创建一个字符集进行匹配的,比如’[pj]thon’与’python’和’jython’都匹配,但是不与其他字符匹配,再比如’[A-Z]’与A到Z之间的任意字符都可以匹配,当然字符集还可以多订以一些匹配项比如’[a-zA-z0-9]’代表匹配所有小写字母、大写字母和数字,但是注意,字符集只能匹配到一个字符。如果要排除某些字符,可以在开头或结尾加上一个^(从开头匹配)或者$(从结尾开始匹配),比如’[^abc]’表示匹配除a、b、c之外的其他任意字符。

二选一和子模式

如果只想匹配连个字符串中的一个比如’python’和’perl’,该怎么办呢?这时可以考虑使用二选一模式,正则表达式使用的是管道字符’|’,表达式就是’python | perl’。

有时不想让二选一运算符用于整个模式,只是想用于模式的一部分,这时可以将二选一模式作为子模式放在圆括号内,上面的例子就可以改成’p(ython|perl)’,单个模式也可以是子模式。

可选模式和重复模式

在子模式后面加上问号,可指定为可选的,即可以包含也可以不包含。比如:

1
r’(http://)?(www\.)?python\.org’

这个表达式表示可以匹配到包括或者不包括’http://’和’www.’的’python.org’字符串,有以下四种情况都可以匹配到:

1
2
3
4
'http://www.python.org'
'http://python.org'
'www.python.org'
'python.org'

这里面对org前面的句点进行了转义,防止其充当通配符。为了少使用’\’这里使用了原字符串的格式,另外每个可选的子模式都在圆括号内包含,这些子模式都是可有可无的。

基于上面的例子,如果想要匹配多个’www.’或者’http://’该怎么做呢?可以使用’*’或者’+’。具体是这样的:

  • (pattern)* : pattern 可重复0、1或多次。
  • (pattern)+ : pattern 可重复1或多次。
  • (pattern){m,n} :模式可从父 m ~ n 次。

例如,r’w*.python.org’ 与 ‘www.python.org'匹配,也与'.python.org' 、 ‘ww.python.org’和’wwwwwww.python.org'匹配。同样,r'w+\.python\.org'与'w.python.org'匹配,但与 ‘.python.org’不匹配,而r’w{3,4}.python.org’只与’www.python.org'和'wwww.python.org'匹配。

贪婪与懒惰模式

当我们使用’.*’进行匹配时,会匹配任意非换行的字符,这有时候可能不会是我们想要的效果,比如
r’aabab’,中我们想要匹配出aab,那么使用’a.*b’对其进行匹配时,返回的结果时aabab,不是我们想要的结果,这是因为在匹配时.*是贪婪匹配模式,会一直匹配到最后的字幕b,要想返回我们想要的aab,必须进行懒惰模式的匹配,即匹配到一个字幕b时就停止匹配。懒惰模式是通过加上一个’?’来实现的。
使用‘a.*?b’就可以匹配到我们想要的aab啦。


2018.08.16新增(来自廖雪峰java基础课程,正则表达式部分)

廖雪峰总能通俗易懂地把内容讲出来,还是厉害。

正则表达式匹配规则:

正则表达式 规则 可以匹配
A 指定字符 A
\u548c 指定Unicode字符
. 任意字符 a, b, &, 0
\d 0-9 0, 1, 2, …, 9
\w a-z, A-Z, 0-9, _ a, A, 0, _, …
\s 空格,Tab键 ‘ ‘, ‘ ‘
\D 非数字 a, A, &, _, …
\W 非\w &, @, 中, …
\S 非\s a, A, @, _, …
AB* 匹配任意个数字符 A,AB, ABB, ABBB, …
AB+ 至少一个字符 AB, ABB, ABBB, …
AB? 0个或1个字符 A,AB
AB{3} 指定个数字符 ABBB
AB{1, 3} 指定范围个数字符 AB, ABB, ABBB
AB{2, } 至少n个字符 ABB, ABBB, …
AB{0, 3} 最多n个字符 A, AB, ABB, ABBB

复杂规则:

正则表达式 规则 可以匹配
^ 开头 字符串开头
$ 结尾 字符串结束
[ABC] […] 内任意字符 A, B, C
[A-F0-9xy] 指定范围的字符 A, …, F, 0, …, 9, x, y
[^A-F] 指定范围外的任意字符 非A, …, F
AB|CD AB或CD AB, CD
AB|CD|EFG AB或CD或EFG AB, CD, EFG