Python正则表达式基础入门
什么是正则表达式
正则表达式(Regular Expression),又称规则表达式,是一种用于描述、匹配和处理字符串的强大工具。在Python中,正则表达式模块re
提供了一系列函数来操作正则表达式。正则表达式本质上是一种小型的、高度专业化的编程语言,它可以用来定义字符串的搜索模式。
正则表达式的作用
- 数据验证:在处理用户输入时,需要确保输入的数据符合特定的格式,比如邮箱地址、电话号码等。例如,验证邮箱地址是否合法,使用正则表达式可以快速判断输入字符串是否符合邮箱格式。
- 数据提取:从大量文本中提取特定格式的数据。比如从一篇网页代码中提取所有的链接,正则表达式能够精准定位并提取出符合链接格式的字符串。
- 文本替换:将文本中符合特定模式的字符串替换为其他内容。例如将一篇文章中的所有手机号码替换为特定的掩码形式,以保护隐私。
Python中的re
模块
Python通过内置的re
模块来支持正则表达式操作。在使用re
模块之前,需要先导入它:
import re
re
模块的常用函数
re.search()
:在字符串中搜索匹配正则表达式的第一个位置,返回一个匹配对象,如果没有匹配则返回None
。
import re
text = "Python is great, Python can be used for data analysis"
match = re.search(r'Python', text)
if match:
print("Match found:", match.group())
else:
print("No match")
在上述代码中,r'Python'
是正则表达式,r
前缀表示这是一个原始字符串,其中的反斜杠不会被解释为转义字符。re.search()
函数在text
字符串中搜索Python
,如果找到则打印匹配的内容。
re.findall()
:在字符串中找到所有匹配正则表达式的子串,并以列表形式返回。
import re
text = "Python is great, Python can be used for data analysis"
matches = re.findall(r'Python', text)
print("Matches:", matches)
这里re.findall()
函数返回了text
字符串中所有出现的Python
子串组成的列表。
re.sub()
:将字符串中所有匹配正则表达式的子串替换为指定的字符串。
import re
text = "Python is great, Python can be used for data analysis"
new_text = re.sub(r'Python', 'Java', text)
print("New text:", new_text)
上述代码将text
字符串中的所有Python
替换为Java
。
正则表达式的基本语法
字符匹配
- 普通字符:普通字符直接匹配自身。例如,正则表达式
abc
会匹配字符串中出现的abc
子串。
import re
text = "abcdef"
match = re.search(r'abc', text)
if match:
print("Match found:", match.group())
else:
print("No match")
- 元字符:具有特殊含义的字符。常见的元字符有
^
、$
、.
、*
、+
、?
、{}
、[]
、()
、|
等。^
:匹配字符串的开头。例如,^Python
表示匹配以Python
开头的字符串。
import re
text1 = "Python is fun"
text2 = "Java is fun"
match1 = re.search(r'^Python', text1)
match2 = re.search(r'^Python', text2)
if match1:
print("Match in text1:", match1.group())
else:
print("No match in text1")
if match2:
print("Match in text2:", match2.group())
else:
print("No match in text2")
- **`$`**:匹配字符串的结尾。例如,`fun$`表示匹配以`fun`结尾的字符串。
import re
text1 = "Python is fun"
text2 = "Python is funny"
match1 = re.search(r'fun$', text1)
match2 = re.search(r'fun$', text2)
if match1:
print("Match in text1:", match1.group())
else:
print("No match in text1")
if match2:
print("Match in text2:", match2.group())
else:
print("No match in text2")
- **`.`**:匹配除换行符`\n`之外的任意单个字符。例如,`a.c`可以匹配`abc`、`aec`等。
import re
text = "abc aec"
matches = re.findall(r'a.c', text)
print("Matches:", matches)
字符类
- 方括号
[]
:用于定义字符类,表示匹配方括号内的任意一个字符。例如,[abc]
表示匹配a
、b
或c
中的任意一个字符。
import re
text = "abcdef"
matches = re.findall(r'[abc]', text)
print("Matches:", matches)
- 范围表示:在方括号内可以使用
-
表示字符范围。例如,[a - z]
表示匹配任意小写字母,[0 - 9]
表示匹配任意数字。
import re
text = "a1b2c3"
matches1 = re.findall(r'[a - z]', text)
matches2 = re.findall(r'[0 - 9]', text)
print("Letter matches:", matches1)
print("Number matches:", matches2)
- 否定字符类:在方括号内开头加上
^
表示否定字符类,即匹配不在方括号内的任意字符。例如,[^a - z]
表示匹配不是小写字母的字符。
import re
text = "a1B"
matches = re.findall(r'[^a - z]', text)
print("Matches:", matches)
量词
*
:表示前面的字符可以出现0次或多次。例如,ab*
可以匹配a
、ab
、abb
等。
import re
text = "a ab abb"
matches = re.findall(r'ab*', text)
print("Matches:", matches)
+
:表示前面的字符可以出现1次或多次。例如,ab+
可以匹配ab
、abb
等,但不匹配a
。
import re
text = "a ab abb"
matches = re.findall(r'ab+', text)
print("Matches:", matches)
?
:表示前面的字符可以出现0次或1次。例如,ab?
可以匹配a
或ab
。
import re
text = "a ab"
matches = re.findall(r'ab?', text)
print("Matches:", matches)
{n}
:表示前面的字符必须出现n
次。例如,a{3}
表示匹配aaa
。
import re
text = "aa aaa aaaa"
matches = re.findall(r'a{3}', text)
print("Matches:", matches)
{n,}
:表示前面的字符至少出现n
次。例如,a{3,}
表示匹配aaa
、aaaa
等。
import re
text = "aa aaa aaaa"
matches = re.findall(r'a{3,}', text)
print("Matches:", matches)
{n,m}
:表示前面的字符至少出现n
次,最多出现m
次。例如,a{2,4}
表示匹配aa
、aaa
、aaaa
。
import re
text = "aa aaa aaaa aaaaa"
matches = re.findall(r'a{2,4}', text)
print("Matches:", matches)
分组与捕获
- 圆括号
()
:用于分组,可以将多个字符作为一个整体进行操作,并且可以捕获匹配的内容。例如,(ab)+
表示匹配ab
出现1次或多次。
import re
text = "ab abab"
matches = re.findall(r'(ab)+', text)
print("Matches:", matches)
- 捕获组:圆括号内的内容形成捕获组,可以通过匹配对象的方法获取捕获组的内容。
import re
text = "John: 25"
match = re.search(r'(\w+): (\d+)', text)
if match:
name = match.group(1)
age = match.group(2)
print("Name:", name)
print("Age:", age)
在上述代码中,(\w+)
和(\d+)
是两个捕获组,match.group(1)
获取第一个捕获组匹配的内容(即名字),match.group(2)
获取第二个捕获组匹配的内容(即年龄)。
非捕获组
在圆括号内开头加上?:
表示非捕获组,它不会捕获匹配的内容。例如,(?:ab)+
表示匹配ab
出现1次或多次,但不捕获ab
。
import re
text = "ab abab"
matches = re.findall(r'(?:ab)+', text)
print("Matches:", matches)
正则表达式的高级应用
零宽断言
- 正向前瞻断言
(?=pattern)
:断言当前位置之后的字符串匹配pattern
,但不包含pattern
本身。例如,Python(?= is great)
表示匹配Python
,但前提是Python
后面跟着is great
。
import re
text = "Python is great"
match = re.search(r'Python(?= is great)', text)
if match:
print("Match found:", match.group())
else:
print("No match")
- 负向前瞻断言
(?!pattern)
:断言当前位置之后的字符串不匹配pattern
。例如,Python(?! is great)
表示匹配Python
,但前提是Python
后面不跟着is great
。
import re
text1 = "Python is easy"
text2 = "Python is great"
match1 = re.search(r'Python(?! is great)', text1)
match2 = re.search(r'Python(?! is great)', text2)
if match1:
print("Match in text1:", match1.group())
else:
print("No match in text1")
if match2:
print("Match in text2:", match2.group())
else:
print("No match in text2")
- 正向后顾断言
(?<=pattern)
:断言当前位置之前的字符串匹配pattern
,但不包含pattern
本身。例如,(?<=is )great
表示匹配great
,但前提是great
前面是is
。
import re
text = "Python is great"
match = re.search(r'(?<=is )great', text)
if match:
print("Match found:", match.group())
else:
print("No match")
- 负向后顾断言
(?<!pattern)
:断言当前位置之前的字符串不匹配pattern
。例如,(?<!is )great
表示匹配great
,但前提是great
前面不是is
。
import re
text1 = "Python great"
text2 = "Python is great"
match1 = re.search(r'(?<!is )great', text1)
match2 = re.search(r'(?<!is )great', text2)
if match1:
print("Match in text1:", match1.group())
else:
print("No match in text1")
if match2:
print("Match in text2:", match2.group())
else:
print("No match in text2")
贪婪与非贪婪匹配
- 贪婪匹配:默认情况下,量词(如
*
、+
、?
、{n,}
、{n,m}
)是贪婪的,即尽可能多地匹配字符。例如,a.*b
会匹配从a
开始到最后一个b
之间的所有字符。
import re
text = "aabab"
match = re.search(r'a.*b', text)
if match:
print("Greedy match:", match.group())
- 非贪婪匹配:在量词后面加上
?
可以使其变为非贪婪匹配,即尽可能少地匹配字符。例如,a.*?b
会匹配从a
开始到第一个b
之间的字符。
import re
text = "aabab"
match = re.search(r'a.*?b', text)
if match:
print("Non - greedy match:", match.group())
正则表达式的编译
re
模块提供了re.compile()
函数,可以将正则表达式编译成正则表达式对象。编译后的对象可以多次使用,提高效率。
import re
pattern = re.compile(r'Python')
text = "Python is great, Python can be used for data analysis"
matches = pattern.findall(text)
print("Matches:", matches)
上述代码先将正则表达式Python
编译成pattern
对象,然后使用该对象的findall()
方法在字符串中查找匹配项。
正则表达式的错误处理
在编写正则表达式时,可能会出现语法错误。re
模块会抛出re.error
异常。例如,以下代码中错误地使用了量词:
import re
try:
re.search(r'a*?', 'abc')
except re.error as e:
print("Error:", e)
在实际应用中,应该使用try - except
块来捕获并处理这些异常,以确保程序的稳定性。
实际案例分析
验证邮箱地址
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9 -]+\.[a-zA-Z0-9-.]+$'
if re.match(pattern, email):
return True
return False
email1 = "test@example.com"
email2 = "test.example.com"
print(validate_email(email1))
print(validate_email(email2))
在上述代码中,^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9 -]+\.[a-zA-Z0-9-.]+$
这个正则表达式用于验证邮箱地址。它的开头^
和结尾$
确保整个字符串都匹配邮箱格式。[a-zA-Z0-9_.+-]+
匹配邮箱用户名部分,@
匹配@
符号,[a-zA-Z0-9 -]+
匹配域名部分,\.
匹配实际的点号,[a-zA-Z0-9-.]+
匹配顶级域名部分。
提取网页链接
import re
def extract_links(html):
pattern = r'href="(.*?)"'
return re.findall(pattern, html)
html = '<a href="https://www.example.com">Example</a><a href="https://www.google.com">Google</a>'
links = extract_links(html)
print(links)
这里r'href="(.*?)"'
这个正则表达式用于从HTML代码中提取链接。href="
匹配href="
字符串,(.*?)
使用非贪婪匹配捕获双引号内的链接内容。
通过以上内容,你应该对Python正则表达式有了较为全面的了解,从基础语法到高级应用,再到实际案例分析,希望这些知识能帮助你在处理字符串相关任务时更加得心应手。