目录
正则表达式(Regular Expression)是一种强大的文本匹配和处理工具,它在各种编程语言和文本编辑器中得到广泛应用。正则表达式提供了一种灵活、高效的方式来搜索、匹配、替换和提取文本数据。Python提供了re模块,它是Python正则表达式操作的标准库。下面是的Python正则表达式教程,介绍了基本的正则表达式语法和如何在Python中使用它们。
正则表达式的作用和优势
- 文本模式匹配:正则表达式可以用于查找特定的文本模式,比如匹配特定格式的日期、时间、电话号码、邮箱地址等。它能够精确地定义匹配规则,从而快速准确地找到符合条件的文本。
- 数据提取:通过正则表达式,可以方便地从文本中提取所需的信息。例如,从HTML代码中提取标签内容,从日志文件中提取关键信息等。
- 数据清洗和处理:正则表达式可以用于对文本数据进行清洗和处理。通过匹配指定的模式并替换、删除或修改文本内容,可以有效地清理和规范化数据。
- 格式验证:正则表达式可以用于验证输入的数据是否符合特定的格式要求。例如,验证邮箱地址、密码强度、身份证号码等。
- 快速搜索和替换:正则表达式提供了强大的搜索和替换功能,可以快速地在文本中查找和替换指定的模式。这在文本编辑器、代码编辑器和命令行工具中非常有用。
- 批量处理和批量操作:正则表达式可以应用于批量处理和批量操作的场景,例如批量重命名文件、批量修改文本内容等。
- 跨平台和通用性:正则表达式在各种编程语言和操作系统中都有支持,因此具有很好的跨平台和通用性。无论是使用Python、Java、JavaScript还是其他语言,都可以使用正则表达式进行文本处理。
正则表达式中一些基本符号
.
:匹配除换行符外的任意一个字符。 示例:a.b
可以匹配 “aab”、“axb”、“a@b” 等。*
:匹配前面的元素零次或多次。 示例:ab*c
可以匹配 “ac”、“abc”、“abbc”、“abbbc” 等。+
:匹配前面的元素一次或多次。 示例:ab+c
可以匹配 “abc”、“abbc”、“abbbc” 等,但不匹配 “ac”。?
:匹配前面的元素零次或一次。 示例:ab?c
可以匹配 “ac”、“abc”,但不匹配 “abbc”。[]
:定义一个字符类,匹配其中任意一个字符。 示例:[aeiou]
可以匹配任意一个小写元音字母。[^]
:在字符类中使用,表示否定。匹配除了字符类中指定的字符之外的任意字符。 示例:[^0-9]
可以匹配任意一个非数字字符。()
:定义一个分组,用于对模式进行分组和捕获。 示例:(ab)+
可以匹配 “ab”、“abab”、“ababab” 等。|
:在两个模式之间进行选择,匹配其中一个。 示例:cat|dog
可以匹配 “cat” 或 “dog”。\
:用于转义特殊字符,或表示特殊序列。 示例:\.
可以匹配一个点字符,而不是任意字符。^
:匹配字符串的开头。 示例:^Hello
可以匹配以 “Hello” 开头的字符串。$
:匹配字符串的结尾。 示例:World$
可以匹配以 “World” 结尾的字符串。{}
:定义重复次数的范围。 示例:a{2,4}
可以匹配 “aa”、“aaa”、“aaaa”,但不匹配 “a” 或 “aaaaa”。\b
:匹配单词边界,即字符前后不是字母、数字或下划线。 示例:\bword\b
可以匹配 “word”,但不匹配 “words” 或 “sword”。\d
:匹配任意一个数字字符,相当于[0-9]
。 示例:\d{3}
可以匹配三位数字。\w
:匹配任意一个字母、数字或下划线字符,相当于[a-zA-Z0-9_]
。示例:\w+
可以匹配一个或多个字母、数字或下划线字符。\s
:匹配任意一个空白字符,包括空格、制表符、换行符等。 示例:Hello\sWorld
可以匹配 “Hello World” 或 “Hello\tWorld”。
常用的正则表达式
- 匹配数字:
^\d+$
可以匹配一个或多个数字。 - 匹配字母:
^[a-zA-Z]+$
可以匹配一个或多个字母。 - 匹配数字和字母:
^[a-zA-Z0-9]+$
可以匹配一个或多个数字和字母的组合。 - 匹配邮箱地址:
^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
可以匹配常见的邮箱地址格式。 - 匹配URL:
^(https?|ftp)://[^\s/$.?#].[^\s]*$
可以匹配常见的URL格式。 - 匹配手机号码:
^1[3456789]\d{9}$
可以匹配中国大陆的手机号码格式。 - 匹配日期(YYYY-MM-DD):
^\d{4}-\d{2}-\d{2}$
可以匹配YYYY-MM-DD格式的日期。 - 匹配时间(HH:MM):
^([01]\d|2[0-3]):[0-5]\d$
可以匹配24小时制的时间格式。 - 匹配IP地址:
^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$
可以匹配IPv4地址。 - 匹配HTML标签:
<(\w+)>(.*)<\/\1>
可以匹配简单的HTML标签,如<p>...</p>
。 - 匹配邮政编码:
^[1-9]\d{5}$
可以匹配6位数字的邮政编码。 - 匹配身份证号码:
^\d{17}[\dXx]$
可以匹配18位数字或17位数字加一个大写字母X(校验位)的身份证号码。 - 匹配电话号码(包括区号):
^(\d{3,4}-)?\d{7,8}$
可以匹配带有可选区号的固定电话号码。 - 匹配用户名:
^[a-zA-Z0-9_-]{3,16}$
可以匹配长度为3到16个字符的用户名,允许字母、数字、下划线和减号。 - 匹配整数:
^-?\d+$
可以匹配正整数或负整数。 - 匹配浮点数:
^-?\d+(\.\d+)?$
可以匹配正浮点数或负浮点数。 - 匹配文件路径(Windows):
^[A-Za-z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$
可以匹配Windows文件路径,如C:\folder\file.txt。 - 匹配中文字符:
[\u4e00-\u9fa5]
可以匹配任意一个中文字符。 - 匹配空白行:
^\s*$
可以匹配只包含空白字符的行。 - 匹配HTML标签(非贪婪模式):
<.*?>
可以匹配HTML标签,但是在遇到第一个闭合的尖括号时停止匹配。
re常用函数
1. 使用search函数进行匹配
re.search(pattern, string, flags=0)
:在字符串中搜索匹配正则表达式的第一个位置,并返回一个匹配对象。
import re
pattern = r"apple"
string = "I have an apple."
match = re.search(pattern, string)
if match:
print("Match found:", match.group())
else:
print("Match not found.")
2. 使用findall函数查找所有匹配项
re.findall(pattern, string, flags=0)
:在字符串中查找所有匹配正则表达式的部分,并返回一个列表。
import re
pattern = r"\d+"
string = "I have 3 apples and 5 oranges."
matches = re.findall(pattern, string)
print(matches)
3. 使用sub函数进行替换
re.sub(pattern, repl, string, count=0, flags=0)
:在字符串中查找匹配正则表达式的部分,并进行替换。
import re
pattern = r"apple"
string = "I have an apple."
new_string = re.sub(pattern, "orange", string)
print(new_string)
4. 使用compile函数编译正则表达式
re.compile(pattern, flags=0)
:编译正则表达式为模式对象,以提高执行效率和复用。
import re
pattern = re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b")
string = "Contact us at [email protected] or [email protected]"
matches = pattern.findall(string)
print(matches)
这些是常用的re模块函数的使用方法。通过这些函数,您可以在字符串中进行正则表达式的匹配、查找和替换操作。请记住,可以通过使用不同的标志和参数来调整匹配行为,并根据需要使用模式对象进行更复杂的操作。
常用正则表达式实例
1.匹配QQ
import re
text = "My QQ is 12345 and yours is 987654321."
qq_pattern = r"[1-9]\d{4,11}"
qq_matches = re.findall(qq_pattern, text)
print(qq_matches) # 输出: ['12345', '987654321']
2.匹配手机号码
import re
text = "My phone number is 13812345678 and yours is 18798765432."
phone_pattern = r"1[3456789]\d{9}"
phone_matches = re.findall(phone_pattern, text)
print(phone_matches) # 输出: ['13812345678', '18798765432']
3.匹配邮箱
import re
text = "My email is [email protected] and yours is [email protected]."
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
email_matches = re.findall(email_pattern, text)
print(email_matches) # 输出: ['[email protected]', '[email protected]']
4.匹配网址
import re
text = "Check out these websites: http://www.example.com, https://www.google.com, www.yahoo.com"
# 匹配网址
url_pattern = r"(http|https)://([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
urls = re.findall(url_pattern, text)
for url in urls:
full_url = url[0] + "://" + url[1]
print(full_url)
# 输出:
# http://www.example.com
# https://www.google.com
提取和操作匹配结果
当使用正则表达式进行匹配时,可以通过匹配结果对象进行提取和操作。以下是一些常用的方法和属性,用于提取和操作匹配结果:
- group():
group()
方法用于获取匹配的字符串。- 可以传递一个可选的参数来指定要获取的捕获分组,默认为 0,表示整个匹配结果。
- 例如,
match.group(1)
可以获取第一个捕获分组的内容。
- groups():
groups()
方法返回一个包含所有捕获分组内容的元组。- 该方法不接受任何参数。
- 例如,
match.groups()
返回包含所有捕获分组的元组。
- groupdict():
groupdict()
方法返回一个字典,其中键是命名分组的名称,值是对应的匹配字符串。- 只适用于具有命名分组的正则表达式。
- 例如,
match.groupdict()
返回一个包含命名分组内容的字典。
- start():
start()
方法返回匹配的起始位置的索引。- 可以传递一个可选的参数来指定要获取的捕获分组的起始位置,默认为 0,表示整个匹配结果的起始位置。
- 例如,
match.start(1)
返回第一个捕获分组的起始位置。
- end():
end()
方法返回匹配的结束位置的索引。- 可以传递一个可选的参数来指定要获取的捕获分组的结束位置,默认为 0,表示整个匹配结果的结束位置。
- 例如,
match.end(1)
返回第一个捕获分组的结束位置。
- span():
span()
方法返回匹配的起始和结束位置的索引构成的元组。- 可以传递一个可选的参数来指定要获取的捕获分组的位置,默认为 0,表示整个匹配结果的位置。
- 例如,
match.span(1)
返回第一个捕获分组的起始和结束位置的索引构成的元组。
通过这些方法和属性,你可以轻松地提取匹配结果中感兴趣的部分,进行进一步的处理和操作。请注意,在使用这些方法之前,确保匹配结果不是 None,即有匹配成功的结果。
贪婪和非贪婪匹配
在正则表达式中,贪婪匹配和非贪婪匹配是指匹配模式的匹配方式。
默认情况下,正则表达式是贪婪的,也就是尽可能多地匹配字符。例如,给定正则表达式a.*b
和字符串a123b456b789
,贪婪匹配会尽可能匹配更多的字符,结果是整个字符串被匹配为a123b456b
。
然而,在某些情况下,我们可能需要非贪婪匹配,也称为最小匹配。非贪婪匹配会尽可能少地匹配字符。在正则表达式中,可以使用?
来表示非贪婪匹配。对于上述例子,非贪婪匹配的正则表达式为a.*?b
,结果会匹配第一个a
和最近的b
,即a123b
。
另一个常见的示例是匹配HTML标签。给定正则表达式<.*>
和字符串<div>some text</div><p>another text</p>
,贪婪匹配会匹配整个字符串,结果是<div>some text</div><p>another text</p>
。而非贪婪匹配的正则表达式为<.*?>
,结果会匹配第一个<div>
。
使用贪婪匹配或非贪婪匹配取决于具体的匹配需求。如果希望尽可能多地匹配字符,可以使用贪婪匹配;如果希望尽可能少地匹配字符,可以使用非贪婪匹配。需要注意的是,非贪婪匹配可能会导致匹配结果不符合预期,因此在使用时需要谨慎评估和调整。
代码实例:
字符串:<div>text1</div><div>text2</div>
正则表达式1:<div>.*</div>
(贪婪匹配)
正则表达式2:<div>.*?</div>
(非贪婪匹配)
import re
text = "<div>text1</div><div>text2</div>"
# 贪婪匹配示例
pattern1 = r"<div>.*</div>"
matches1 = re.findall(pattern1, text)
print("贪婪匹配结果:")
for match in matches1:
print(match)
# 非贪婪匹配示例
pattern2 = r"<div>.*?</div>"
matches2 = re.findall(pattern2, text)
print("\n非贪婪匹配结果:")
for match in matches2:
print(match)
运行以上代码,输出如下:
贪婪匹配结果:
<div>text1</div><div>text2</div>
非贪婪匹配结果:
<div>text1</div>
在这个示例中,我们使用re.findall()
函数来找到匹配正则表达式的所有结果。pattern1
使用贪婪匹配方式,导致整个字符串被匹配;而pattern2
使用非贪婪匹配方式,只匹配了第一个<div>
与最近的</div>
之间的内容。
- 📢博客主页:https://blog.csdn.net/qq233325332
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 陌北v1 原创,首发于 CSDN博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨