其他教程

其他教程

Products

当前位置:首页 > 其他教程 >

正则表达式如何全部表达

GG网络技术分享 2025-03-18 16:14 1


问题描述:

import re

def ab(s):

regex1=re.compile(r'\\(.*?\\)')

mo=regex1.findall(s)

print(mo)

ab('(AA(BB)CC)')

输出的结果是:

['(AA(BB)']

如何把(BB)输出。按理非贪心获得最小的。

网友观点:

****(\\w+?)

把.* 改成\\w+即可

regex1 = re.compile(r'(.?((.?)).*?)')

正则表达式知识总结

### 1、前言

正则表达式,如果有一定编程经验的同学,一定知道,可能你知道,但又说不出个所以然来,平时不经常使用,很容易就忘记,有一部分原因,我认为是总结的内容,不够简单和深刻。所以,自己尝试总结一下正则表达式的基础知识点,对于大部分的编程场景应该足够使用啦。另外,也希望通过总结,以便后续忘记时,能快速的记忆起来,这就是本文章的主要内容。


<!--more-->


### 2、正则表达式

![RegularExpression.png](https://github.com/iHTCboy/iGallery/raw/master/BlogImages/2020/10/RegularExpression.png)



#### 匹配字符集

| 语法 | 匹配 | 示例 |

|---|---|---|

| `.` | 匹配任意字符(除了`\\n`) | 表达式:`.` 匹配任意一个字符 |

| `[...]` | 匹配字符集(`...` 表示任意字符) | 表达式:`[a-zA-Z]` 匹配任意一个小写或大写的字母。<br>表达式:`[iHTC]` 匹配 "i", "H", "T" 和 "C"。<br>表达式:`[e-k]` 匹配 "e" 到 "k" 之间的字符。|

| `\\d` | 匹配数字 | 表达式:`a\\d`,匹配字符串 "aaa123" 中的 **a1** 。<br>表达式:`a.\\d`,匹配字符串 "aaa123" 中的 **aa1** 。|

| `\\D` | 匹配非数字 | 表达式:`a.\\D`,匹配字符串 "aaa123" 中的 **aaa** 。|

| `\\s` | 匹配空白字符(包括空格、制表符、换页符等空白字符,`[ \\t\\n\\r\\f]`) | 表达式:`a.\\s`,匹配字符串 "aaa 123" 中的 `aa `(最后是空格) 。|

| `\\S` | 匹配非空白字符 | 表达式:`a.\\S`,匹配字符串 "aaa 123" 中的 **aaa** 。|

| `\\w` | 匹配单词字符([a-zA-Z0-9_]和汉字) | 表达式:`a.\\w`,匹配字符串 "aaa 123" 中的 **aaa** 。|

| `\\W` | 匹配非单词字符 | 表达式:`a.\\W`,匹配字符串 "aaa 123" 中的 `aa `(最后是空格) 。|

| `\\` | 转义字符 | `\\r`, `\\n` 代表回车和换行符; `\\t` 制表符; `\\\\` 代表 "\\" 本身; `\\^` 匹配 ^ 符号本身; `\\$` 匹配 $ 符号本身; `\\.` 匹配小数点(.)本身。 |


#### 匹配量词(Quantifier)

| 语法 | 匹配 | 示例 |

|---|---|---|

| `*` | 匹配表达式出现 0次或者无限次,相当于 {0,} | 表达式:`a*`,匹配字符串 "aaa123" 中的 **aaa** 。|

| `+` | 匹配表达式至少出现 1次或者无限次,相当于 {1,} | 表达式:`a+`,匹配字符串 "aaa123" 中的 **aaa** 。 |

| `?` | 匹配表达式 0次或者 1次,相当于 {0,1} | 表达式:`a?`,匹配字符串 "aaa123" 中的 **a** 。 |

| `{m,n}` | 匹配表达式至少重复 m 次,最多重复 n 次 | 表达式:`a{1,2}`,匹配字符串 "aaa123" 中的 **aa** 。 |

| `{m}` | 匹配表达式重复 m 次 | 表达式:`a{3}`,匹配字符串 "aaa123" 中的 **aaa** 。 |

| `{m,}` | 匹配表达式至少重复 m 次 | 表达式:`a{1,}`,匹配字符串 "aaa123" 中的 **aaa** 。 |

| `*?` | 匹配模式变为非贪婪(尽可能少匹配字符),匹配表达式可以为 0次,也可以是无限次 | 表达式:`a[0-9]*?23'`,匹配字符串 "aaa123" 中的 **a123** 。<br>如果匹配字符串 "aaa23" 则为 **a23** 。<br>如果匹配字符串 "aaa456123" 则为 **a456123** 。 |

| `+?` | 匹配模式变为非贪婪(尽可能少匹配字符),匹配表达式至少 1次,也可以是无限次 | 表达式:`a[0-9]+?23`,匹配字符串 "aaa123" 中的 **a123** 。<br>如果匹配字符串 "aaa23" 则匹配失败 。<br>如果匹配字符串 "aaa456123" 则为 **a456123** 。 |

| `??` | 匹配模式变为非贪婪(尽可能少匹配字符),匹配表达式最多 1次,也可以是 0次 | 表达式:`a[0-9]??23`,匹配字符串 "aaa123" 中的 **a123** 。<br>如果匹配字符串 "aaa23" 则为 **a23** 。<br>如果匹配字符串 "aaa456123" 则匹配失败。|

| `{m,n}?` | 非贪婪模式,匹配符合的最短的字符串 | 表达式:`a[0-9]{1,4}?23`,匹配字符串 "aaa123" 中的 **a123** 。<br>如果匹配字符串 "aaa23" 则匹配失败 。<br>如果匹配字符串 "aaa456123" 则为 **a456123** |


#### 匹配边界

| 语法 | 匹配 | 示例 |

|---|---|---|

| `^` | 匹配字符串开头 | 表达式:`^\\d` 表示必须以数字开头。<br>表达式:`[^abc]` 匹配 `a`, `b`, `c` 之外的任意一个字符。 |

| `$` | 匹配字符串结尾 | 表达式:`*.com$` 匹配 .com 结尾的字符串。<br> `\\d$`表示必须以数字结束。 |

| `\\A` | 指定的字符串匹必须出现在开头 | 表达式:`\\Aa`,匹配字符串 "aaa123" 中的 **a** 。 |

| `\\Z` | 指定的字符串匹必须出现在结尾。如果是存在换行,只匹配到换行前的结束字符串。 | 表达式:`\\d\\Z`,匹配字符串 "aaa123" 中的 **3** 。 |

| `\\b` | 匹配一个单词边界,但只在单词开始或结尾的位置,即匹配 `\\w` 和 `\\W ` 之间。(本身不匹配任何字符) | 表达式:`\\b4`,匹配字符串 "aaa123 456" 中的 **4** 。<br>表达式:`\\b5`,匹配字符串 "aaa123 456" 则为失败。 |

| `\\B` | 匹配非单词边界,但不能在词的开头或者结尾,即匹配 `[^\\b]` 。(本身不匹配任何字符) | 表达式:`\\B4`,匹配字符串 "aaa123 456" 则为失败。<br>表达式:`\\B5`,匹配字符串 "aaa123 456" 中的 **5** 。 |


#### 匹配条件分组

| 语法 | 匹配 | 示例 |

|---|---|---|

| `⎮` | 或关系,匹配左右任意一个表达式 | 表达式:`a⎮b`,匹配字符串 "aaa123" 中的 **a** 。|

| `(ab)` | 括号中表达式作为一个分组 | 表达式:`(a1)`,匹配字符串 "aaa123" 中的 **a1** 。<br>表达式:`(P⎮p)ython`,可以匹配 **Python** 或者 **python**。 |

| `(?:exp)` | 表示非捕获分组,匹配 pattern 但不获取匹配结果。 | 表达式:`([a-z]*)([0-9]*)([a-z]*)`,匹配字符串 `"aaa123def456"` 中的 **'aaa', '123', 'def'** 。<br>表达式:`(?:[a-z]*)([0-9]*)([a-z]*)`,匹配字符串 "aaa123def456" 中的 **'123', 'def'** 。 |

| `\\<number>` | 引用编号为 number 的分组(规则)匹配到的字符串 | 表达式:`(\\d)def\\1`,匹配字符串 "aaa123def321" 中的 **3def3** 。 |

| `(?P<name>)` | 给分组起一个别名 name | 表达式:`(?P<tag>\\d)def(?P=tag)`,匹配字符串 "aaa123def321" 中的 **3def3** 。 |

| `(?P=name)` | 引用别名为 name 的分组匹配字符串 | 表达式:`<(?P<tag>\\w*)>.*</(?P=tag)>`,匹配字符串 `<html><h1>iHTCboy's blog</h1><html>` 中的 `<h1>iHTCboy's blog</h1>` 。 |



#### 预搜索

| 语法 | 匹配 | 示例 |

|---|---|---|

| `(?=exp)` | 断言自身出现的位置的后面能匹配表达式 exp,exp1(?=exp2):查找 exp2 前面的 exp1。| 表达式:`Windows(?=7)` 能匹配**Windows7** 中的 “Windows”,但不能匹配 **Windows10** 中的“Windows”。 |

| `(?!exp)` | 断言自身出现的位置的后面不能匹配表达式 exp,exp1(?!exp2):查找后面不是 exp2 的 exp1。| 表达式:*Windows(?!7)* 能匹配**Windows10** 中的“Windows”,但不能匹配 **Windows7** 中的“Windows”。 |

| `(?<=exp)` | 断言自身出现的位置的前面能匹配表达式 exp,(?<=exp2)exp1:查找 exp2 后面的 exp1。| 表达式:`(?<=7)Windows` 能匹配 **7Windows** 中的“Windows”,但不能匹配 **10Windows** 中的“Windows”。 |

| `(?<!exp)` | 断言自身出现的位置的前面不能匹配表达式 exp,(?<!=exp2)exp1:查找前面不是 exp2 的 exp1。| 表达式:`(?<!7)Windows` 能匹配 **10Windows** 中的“Windows”,但不能匹配 **7Windows** 中的“Windows”。 |


> exp :expression(表达式)


#### 匹配模式


| 类型 | 模式 |说明|

|---|---|---|

| `IGNORECASE` | 忽略大小写模式 | 匹配时忽略大小写。(正则默认是区分大小写的) |

| `SINGLELINE` | 单行模式 | 整个文本看作一个字符串,只有一个开头一个结尾 |

| `MULTILINE` | 多行模式 | 每行都是一个字符串。在多行模式下,如果需要仅匹配字符串开始和结束位置,可以使用 \\A 和 \\Z |



### 3、Python 正则表达式


如果使用编辑语言来执行正则表达式呢?所有语言都是相通的,这是记录了之前使用 Python 的 re 模块做正则匹配的功能。


#### compile 和 match 函数


`re.compile` 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match()、search() 等函数使用。

`re.match` 尝试从字符串的起始位置匹配一个模式,如果字符串开始不符合正则表达式,就返回 None 。


```python3

result = re.match(pattern, string)

```


等价于


```python3

prog = re.compile(pattern)

result = prog.match(string)

```


> 注:如果需要多次使用这个正则表达式的话,使用 `re.compile()` 保存这个正则对象以便复用匹配多个字符串,可以让程序更加高效。


#### search 函数


`re.search` 扫描整个字符串并返回第一个成功的匹配。如果没有匹配,就返回一个 None 。


```python3

re.search(pattern, string, flags=0)

```



示例:

```python3

>>> re.search('iHTCboy', 'iHTCboy's blog')

>>>

<re.Match object; span=(4, 11), match='iHTCboy'>

```


我们可以使用 `group(num)` 或 `groups()` 匹配对象函数来获取匹配表达式。



```python3

>>> searchObj = re.search( r'(.*) are (.*?) .*', "iHTCboy are my nikename)

>>> print(searchObj.group())

>>> print(searchObj.groups())

>>> print(searchObj.group(1))

>>> print(searchObj.group(2))

>>>

iHTCboy are my nikename

('iHTCboy', 'my')

iHTCboy

my

```



#### findall 函数

`re.findall` 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。



```python3

re.findall(pattern, string, flags=0)

```


> 对 `string` 返回一个不重复的 `pattern` 的匹配列表, `string` 从左到右进行扫描,匹配按找到的顺序返回。如果样式里存在一到多个组,就返回一个组合列表;就是一个元组的列表(如果样式里有超过一个组合的话)。空匹配也会包含在结果里。



比如查找字符串中的所有数字:

```python3

>>> result2 = re.findall(r'\\d+', 'abc123d4efg567')

>>>

['123', '4', '567']

```


查找不是以 4、7 结尾的手机号码(11位)手机号码:

```python3

>>> result2 = re.findall(r'^1\\d{9}[0-35-68-9]$', 'xxxxx')

>>>

```


#### finditer 函数


和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。


```python3

re.finditer(pattern, string, flags=0)

```


搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器:

```

>>> for m in re.finditer(r'\\d+', 'abc123d4efg567'):

>>> print(m.group())

>>>

123

4

567

```



#### split 函数

`re.split` 方法按照能够匹配的子串将字符串分割后返回列表。


```python3

re.split(pattern, string, maxsplit=0, flags=0)

```

> 用 `pattern` 分开 `string` 。如果 `maxsplit` 非零, 最多进行 `maxsplit` 次分隔, 剩下的字符全部返回到列表的最后一个元素。


对于规则的字符串,比如 `abc` 我们一般可以用 split 函数分割,但是如果遇到 `a b c` 这样的字符串,得到的结果就是 `['a', 'b', '', '', 'c']`。所以,你可能需要人工来自己再次过滤,而使用正则表达式来处理,就显示很轻松:



```python3

>>> re.split(r'[\\s\\,]+', 'a,b, c d')

>>>

['a', 'b', 'c', 'd']

```


上面的 `[\\s\\,]+` 表示匹配 `\\s` (空格)和 `,` 中任意一个至少一次的分割。



对于一个找不到匹配的字符串而言,split 不会对其作出分割。


```python3

>>> re.split('a*', 'hello iHTCboy')

>>>

['hello iHTCboy']

```



#### sub 函数

`re.sub` 用于替换字符串中的匹配项。


```python3

re.sub(pattern, repl, string, count=0, flags=0)

```


> 返回通过使用 `repl` 替换在 `string` 最左边非重叠出现的 `pattern` 而获得的字符串。 如果样式没有找到,则不加改变地返回 string。 `repl` 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理。 也就是说,`\\n` 会被转换为一个换行符,`\\r` 会被转换为一个回车附,依此类推。



比如电话号码格式可能带有空格或者-时,可以替换为空字符串:


```python3

>>> re.sub(r'\\D', "", "188-8888-8888")

>>>

18888888888

```


`repl` 参数可以是一个函数,用于对匹配的内容进行更多的逻辑处理:


```python3

# 将匹配的数字乘以 2

>>> def double(matched):

>>> value = int(matched.group('value'))

>>> return str(value * 2)

>>>

>>> re.sub('(?P<value>\\d+)', double, 'abc123d4efg567')

>>>

abc246d8efg1134

```



### 总结


正则表达式的内容有非常的多,如果不经常使用的话,可以就会很快忘记。所以,正则其实是不是应该记住呢?其实,应该是要记住,如果记不住,要不要紧?其实,是不要紧,因为正则就想查表一下,你如果之前已经比较系统的学习过,忘记了规则,看一下本文就大概记起来了。所以,这就是本文的目的,总结性的文章,不需要太多的复杂,简单又快捷的总结。


国庆中秋双节快乐!这篇文章应该是去年9月就定下来但迟迟没有动手,现在又过一年了,感叹生活真快。好好学习,天天快乐~



### 参考

- [python正则表达式_python正则表达式教程_python正则表达式视频教程-慕课网](python正则表达式_python正则表达式教程_python正则表达式视频教程-慕课网)

- [re --- 正则表达式操作 — Python 3.8.6 文档](https://docs.python.org/zh-cn/3/library/re.html#)

- [正则表达式 - 笔记](RegularExpression · iHTCboy学习笔记)


<br>


- 如有疑问,欢迎在评论区一起讨论!

- 如有不正确的地方,欢迎指导!


<br>


> 注:本文首发于 [iHTCboy's blog](iHTCboy's blog),如若转载,请注来源


<br>

标签:

提交需求或反馈

Demand feedback