python--正则表达式

一、正则表达式的概念

正则表达式是一种"匹配模式的语言",它用来告诉计算机我们想在一段文字中找到什么样的内容。是一种非常高级的搜索工具。

正则表达式的基本组成部分:

1、普通字符:直接匹配自身的字符 ,比如w匹配字符'w'

2、元字符(Metacharacters):具有特殊含义的字符。

(1) '.' 匹配除换行符以外的任意单个字符 例如:a.b 匹配acb、a1b、a@b等

(2)'^' 匹配字符串的开头 例如: ^hello - 只有以hello开头才匹配

(3)'' 匹配字符串的结尾 例如:world 只有以world结尾才匹配

(4)'*' 前一个字符出现0次或多次 例如:ab* 匹配 a、ab、abbb等

(5)'+' 前一个字符出现1次或多次 例如:ab+ 匹配 ab、abb、abbb等

(6)'?' 前一个字符出现0次或一次 例如 ab?匹配 a、ab

(7) ' ' 匹配括号里任意一个字符 例如 abc 匹配a、b、c其中一个

(8) ' | ' 逻辑或 例如a|b 匹配a或者b

(9)'()' 分组、提取内容、改变优先级 例如 (ab)+ → 匹配 abababababab

3、转义字符:用于将元字符当作普通字符对待,通常用反斜杠 \ 如\.匹配一个点

4、量词:指定匹配的数量。 {n}:精确匹配n次 {n,} 至少匹配n次 {n,m}:匹配n到m次。

示例1 查找特定单词

welcome to beijing, beijing is the capital of china

如果我想查找所以的beijing单词,我可以用beijing这个正则表达式来做这件事,正则表达式会匹配并找到所有beijing这个单词

import re

text1 = 'welcome to beijing, beijing is the capital of china'

result = re.findall(r'beijing', text1)

print(result)

示例2:灵活匹配不同的单词

假如我想找beijing 还想找beijingtiananmen 那可以使用beijing(tiananmen)? 这个正则表达式

import re

text1 = 'welcome to beijing, beijing is the capital of china,beijingtiananmen very beautiful'

result = re.findall(r'beijing(?:tiananmen)?', text1)

print(result)

findall 只返回捕获组

将捕获组 () 改为非捕获组 (?:),这样 findall 就会返回整个正则的匹配结果

示例3:匹配邮件地址

import re

text2= 'email: 123456@qq.com, 123abc@163.com, 1wwq6@126.com'

email = re.findall(r'\w+@\w+\.\w+',text2)

print(email)

\w+ 匹配1个或多个字母、数字或下划线

A-Za-z0-9._%+-+@A-Za-z0-9.-+\.A-Za-z{2,4} 这种方法更精确

为什么要学正则表达式?

提高工作效率:在文本处理任务中,使用正则表达式可以显著减少代码量,并且能够快速、准确地处理数据。

通用性强:正则表达式不仅适用于Python,还能在许多编程语言中使用,如JavaScript、Java等,甚至在一些文本编辑器中也可以使用。

解决复杂问题:当你需要从大量文本中提取特定信息,或进行复杂的搜索和替换时,正则表达式是非常有效的工具。

二、正则表达式基础

1、字符匹配

import re

text1 = "hello"

text2 = "h.llo"

match = re.match(text2,text1)

if match:

print(match.group())

else:

print("no match")

输出 hello

代码解释:

text1 = "hello":定义了一个待匹配的字符串 text1。

text2 = "h.llo":定义了一个正则表达式模式 text2。这里的 . 是一个特殊字符,表示可以匹配除换行符之外的任何一个字符。所以,这个模式可以匹配 "hello",也可以匹配 "hallo",但不能匹配 "hlllo"。

match = re.match(text2, text1):使用 re.match() 函数尝试将模式 pattern 从字符串 text 的开头进行匹配。如果匹配成功,返回一个匹配对象,否则返回 None。

if match::检查是否有匹配对象。如果有,表示匹配成功。

print("匹配成功:", match.group()):如果匹配成功,打印匹配的内容。match.group() 返回匹配的字符串。

else: print("匹配失败"):如果没有匹配成功,则打印 "匹配失败"。

2、字符集

import re

text1 = "hHello"

print(re.match(text1,"hello"))

print(re.match(text1,"Hello"))

这里的 "hH" 表示一个字符集,h 或 H 都可以匹配。正则表达式要求字符串以 "h" 或 "H" 开头,后面跟着 "ello"。

3、重复匹配

import re

text1 = "a+b*c"

print(re.match(text1,"aabbc"))

print(re.match(text1,"ac"))

a+b*c意思就是 有一个或多个a 0个或多个b 一个c (abc顺序不能乱哦)

4、特殊字符

import re

text1 = r"\d+\s\w+"

text2 = "123 abc"

r = raw string(原始字符串) 告诉 Python:不要把反斜杠 \ 当成转义符,就当普通字符。

\d+ : 匹配一个或多个数字

\s : 匹配一个空白字符

\w+: 匹配一个或多个字母、数字或下划线

匹配时严格按照顺序关系。

5、边界匹配

import re

text1 = "^hello"

print(re.match(text1, "hello world"))

print(re.match(text1, "world hello"))

匹配以字符串hello开头的

6、常用的正则表达式函数

1、re.match() 从字符串开头开始匹配

import re

text1 = r"\d{3}-\d{3,8}"

print(re.match(text1, "010-12345")) 匹配

print(re.match(text1, "01022-1234")) 不匹配

这个意思就是匹配3位数字加-加3-8位的数字

\d
含义:\d 是一个预定义字符类,表示匹配任意一个数字字符(即 0-9)。
等价于0-9
{3}
含义:花括号 {n} 表示前面的元素必须出现恰好 n 次。
在这里:\d{3} 表示匹配恰好三个连续的数字。
\d{3,8}
含义:\d{3,8} 表示匹配 3 到 8 个连续的数字。
解释:花括号 {n,m} 表示前面的元素可以出现至少 n 次,最多 m 次。在这里,
\d{3,8} 表示可以匹配 3 到 8 个数字。
2、re.search()
re.search()方法用于搜索字符串中首次出现的匹配项。与match()不同,search()可以匹配字符串任意位置
import re

text1 = r"\d{3}-\d{3,8}"

print(re.search(text1, "my 010-12345 but your 012-123456"))

只匹配第一个010-12345

3、re.findall()

re.find()方法用于查找字符串中所有非折叠的匹配项,并以列表形式返回
import re

text1 = r"\d{3}-\d{3,8}"

print(re.findall(text1, "my 010-12345 but your 012-123456"))

返回:'010-12345', '012-123456'
• re.findall() 返回所有匹配项的列表。如果没有匹配项,则返回空列表。
假设我们有一个字符串 "ababa",我们想要找到 "aba" 这个模式。
import re

text1 = "aba"

text2 = "ababa"

print(re.findall(text1, text2))
输出'aba'
解析:
在字符串 "ababa" 中,虽然有两个 "aba" 出现的可能性(第一个从索引 0 开始,第
二个从索引 2 开始),但 re.findall() 只会匹配第一次出现的 "aba",然后继续从匹配
后的字符(即从索引 3 开始)进行查找。由于从索引 3 开始再没有 "aba" 出现,所
以结果中只有一个匹配。
4. re.sub()
re.sub()方法用于替换字符串中所有匹配的子字符串。它的语法为re.sub(pattern,repl,string,count=0), 其中pattern是正则表达式,repl是替换内容,string是要处理的字符串,用于指定替换的最大次数(默认为0,表示替换所有匹配项)。
import re

text1 = r"\d{3}-\d{3,8}"

text2 = "my 010-12345 but your 012-123456"

print(re.sub(text1, "000-0000", text2,count=1))、

把匹配到的替换成000-0000 count1代表匹配1次

my 000-0000 but your 012-123456

5、re.split()
re.split() 方法根据模式中的匹配项来拆分字符串,并返回拆分后的列表
import re

text1 = r"\s+"

text2 = "This is a simple sentence."

words = re.split(text1, text2)

print("拆分后的列表:", words) # 输出 "This", "is", "a", "simple", "sentence."
s+是匹配1个或多个空白符
6. re.compile()
re.compile() 方法用于预编译正则表达式。预编译的正则表达式对象可以复用,以提高效率,
特别是在多次使用同一正则表达式时。
代码示例:
import re

编译正则表达式

pattern = re.compile(r"\d{3}-\d{3,8}")

使用编译后的模式

text = "My number is 123-4567 and my friend's number is 987-6543210."

matches = pattern.findall(text)

print("找到的所有匹配项:", matches) # 输出 "123-4567", "987-6543210"

继续使用编译后的模式进行匹配

match = pattern.search(text)

if match:

print("首次匹配:", match.group()) # 输出 "123-4567"
解释:
• re.compile() 返回一个正则表达式对象,该对象可以使用 match(), search(), findall(),
sub() 等方法。

三、实战案例

1、假设你有一个Apache日志文件access.log,内容如下:

192.168.0.1 - - 28/Aug/2030:10:22:04 +0000 "GET /index.html HTTP/1.1" 200 2326
203.0.113.45 - - 28/Aug/2030:10:22:05 +0000 "POST /login.php HTTP/1.1" 200 342
192.168.0.2 - - 28/Aug/2030:10:22:06 +0000 "GET /dashboard HTTP/1.1" 200 128

我要过滤出ip地址

import re

with open('file/access.log','r') as f:

for line in f:

xx = re.split(r"\s",line)

ip = xx0

print(ip)

输出 :

192.168.0.1

203.0.113.45

192.168.0.2

2、假设有两个数据库配置文件 我想修改两个文件中的用户名

config1.conf
DB_CONNECTION="mysql://user1:password@localhost/db1"
config2.conf
DB_CONNECTION="mysql://user1:password@localhost/db2"
代码:
import re

config_files = "file/config1.conf","file/config2.conf"

pattern = r'(DB_CONNECTION="mysql://)(\w+)(:password@localhost/db12")'

new_name = 'admin'

for file in config_files:

with open(file,"r") as f:

content = f.read()

new_content = re.sub(pattern,r'\1'+new_name+r'\3',content)

with open(file,"w") as f:

f.write(new_content)

print("file {} has been updated".format(file))

解析:

r'\1' + new_name + r'\3' 替换规则
\1 = 保留第 1 段不动
new_name = 把中间的用户名改成 admin
\3 = 保留第 3 段不动

3、 检查配置文件中的缺失项

我想检查配置文件是否都包含max_connection 这个设置项

import re

config_files = "file/config1.conf","file/config2.conf"

pattern = r"max_connections\s*=\s*(\d+)"

for file in config_files:

with open(file,"r") as f:

content = f.read()

pz = re.search(pattern,content)

if pz:

print("{file} have mc")

else:

print("{file} have not mc")

解析:

  • \s* = 0 个 或 多个 空格
  • 意思就是:等号前面有没有空格都能匹配
相关推荐
来恩10031 天前
Java正则表达式
正则表达式
水木流年追梦2 天前
大模型入门-大模型分布式训练2
开发语言·分布式·python·算法·正则表达式·prompt
水木流年追梦2 天前
大模型入门-大模型分布式训练1
开发语言·分布式·python·算法·正则表达式·prompt
我材不敲代码4 天前
Python 正则表达式实战总结
数据库·python·正则表达式
水木流年追梦4 天前
大模型入门-大模型的推理策略
开发语言·python·算法·正则表达式·prompt
水木流年追梦4 天前
大模型入门-DPO 直接偏好优化
人工智能·学习·算法·机器学习·正则表达式
asdfg12589635 天前
使用正则表达式str.split(“\\W+“)拆分句子
java·正则表达式
我材不敲代码5 天前
Python 正则表达式进阶实战:从文本清洗到复杂信息提取
c++·python·正则表达式
水木流年追梦6 天前
大模型入门-Reward 奖励模型训练
开发语言·python·算法·leetcode·正则表达式