正则大家都不陌生,工作中一定会接触到。最近在Python中用的了正则,所以顺便整理一下。
一、re模块的使用
#导入 re模块
import re
# 使用match方法进行匹配操作
result = re.match(正则表达式, 要匹配的字符串)
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
re.match 是用来进行正则匹配检查的方法,如果字符串匹配正则表达式,则match方法返回匹配对象,否则返回None
二、表示字符等
字符 | 功能 |
. | 匹配任意一个字符(除了\n) |
[] | 匹配[]中列举的字符 |
\d | 匹配数字,也就是0-9 |
\D | 匹配非数字 |
\s | 匹配空白,即空格、tab键 |
\S | 匹配非空白 |
\w | 匹配单词字符 即a-z、A-Z、0-9、_ |
\W | 匹配非单词字符 |
如果[]里以^开头表示非的意思。
import re
ret = re.match(".", "M")
print(ret.group())
p = "1[345]" # 这个正则也就是匹配13、14、15 这三种情况
result1 = re.match(p, '12') #不匹配
print(result1)
result2 = re.match(p, '13') # 匹配
print(result2)
rP = "1[^345]" # [] 里面有个 ^ 表示取反的意思也就是不是这三个数的情况
result1 = re.match(rP, '12') #匹配
print(result1)
result2 = re.match(rP, '13') #不匹配
print(result2)
print("----------------------------------------------")
result = re.match('\d', "13") # 数字
print(result)
result = re.match("嫦娥\d号","嫦娥3号发射成功")
print(result)
三、原始字符
就是在正则里面有可能出现转义的情况。在正则表达式里面使用“\”来表示转义,比如你要匹配“\”,这个时候正则需要“\\”,有时候这个斜杠可能遗漏等问题。Python里的原生字符串很好地解决了这个问题,有了原始字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
import re
#转义
result = re.match('\\\\n\w', '\\nab')
print(result)
# 原始字符
s = r'\nabc'
print(s)
result = re.match(r'\\n\w', r'\nab')
print(result)
四、表示数量
字符 | 功能 |
* | 匹配前一个字符0次或者无限次,即可有可无 |
+ | 匹配前一个字符1次或者无限次,即至少1次 |
? | 匹配前一个字符出现一次或者0次,即要么1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,} | 匹配前一个字符至少出现m次 |
{m,n} | 匹配前一个字符出现m到n次 |
五、表示边界
字符 | 功能 |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词边界 |
说到开头和结尾想到vi编辑器里面鼠标移动到开头的位置就是 ^, 光标移动到结尾的位置就是$
import re
# ^ 开始
# $ 末尾 , 其实在 vi 编辑器里面光标去头还是未也是这样的
result = re.match(r'^\w+\bve\b', 'hover')
print(result)
result = re.match(r'^\w+\bve\b', 'ho ve r')
print(result)
# \b 不能匹配空格
result = re.match(r'^\w+\sve\b', 'ho ve r')
print(result)
result = re.match(r'^.+ve\b', 'ho ve r')
print(result)
六、匹配分组
字符 | 功能 |
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用分组num匹配到字符串 |
(?P<name>) | 分组起别名 |
(?P=name) | 引用别名为name分组匹配到字符串 |
比如现在要表示0-100之间的数字?
import re
#正则表示 0 - 100
result = re.match(r"[1-9]\d?$|0|100", '0')
print(result)
result = re.match(r"[1-9]?\d?$|100", '0')
print(result)
假设现在要匹配“<html><h1>helo world</h1></html>” 这样的字符?
import re
#<html><h1>helo world</h1></html>
# \1 \2 提取的位置
result = re.match(r"<(.+)><(.+)>.+</\2></\1>", '<html><h1>helo world</h1></html>')
print(result)
result = re.match(r"<(.+)><(.+)>.+</\2></\1>", '<html><h1>helo world</h1></h1>') # 匹配不成功
print(result)
另外如果标号太麻烦的话,可以分组起名来写。
import re
# 分组起名
result = re.match(r"<(?P<Key1>.+)><(?P<Key2>.+)>.+</(?P=Key2)></(?P=Key1)>", '<html><h1>helo world</h1></html>')
print(result)
七、re的高级用法,search、findall、sub
import re
result = re.search(r"\d", 'asdf0')
print(result)
result = re.search(r"^\d$", 'asdf0')
print(result)
# search 只能找到一个
s = 'mar</h1>hellow od</h1>'
result = re.search(r'\w+</h1>', s)
print(result)
# findall 可以找到所有的
s = 'mar</h1>hellow lod</h1>'
result = re.findall(r'\w+</h1>', s)
print(result)
#sub 将匹配到的数据进行替换
# ret = re.sub(r"要替换的正则", '要替换的值', "要修改的字符串")
# 把 t 中的 php 都换成 python
t = "c++ php python shell window php python"
ret = re.sub(r"php", 'python', t)
print(ret)
print("---------------------------------------------------------------------------------")
# 现在要有目的的去替换
def replace(result):
r = int(result.group()) + 20
# 在原有的值上面加 20
return str(r)
ret = re.sub(r'\d+', replace, 'python = 100, php = 10')
print(ret)
八、Python贪婪和非贪婪
Python中的数量词默认的贪婪模式,总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。比如看下面这个例子。
import re
s = "This is a number 234-235-22-423"
r = re.match(".+(\d+-\d+-\d+-\d+)",s)
print(r.group(1))
s = "This is a number 234-235-22-423"
r = re.match("(.+)(\d+-\d+-\d+-\d+)",s) #前面的(.+) 是贪婪的,尽可能匹配多的
print(r.groups())
#在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
s = "This is a number 234-235-22-423"
r = re.match("(.+?)(\d+-\d+-\d+-\d+)",s) #前面的(.+) 是贪婪的,尽可能匹配多的
print(r.groups())