1. 正则表达式是什么?
正则表达式是一种用于匹配字符串的语言。它由一系列字符和特殊符号组成,用来描述搜索模式。在Python中,
1 | re |
模块提供了支持正则表达式的功能。
2. 安装与导入
首先,确保你的Python环境中已经安装了
1 | re |
模块。这是Python的标准库之一,所以通常不需要额外安装。
1 import re
3. 字符匹配
- 单个字符:使用方括号
1[]
表示一组字符中的任意一个。
1 <em># 匹配任何字母</em><br>pattern = "[a-zA-Z]"<br>string = "Hello World!"<br>match = re.search(pattern, string)<br>print(match.group()) <em># 输出: H</em>
- 多个字符:使用
1*
表示零次或多次出现。
1 <em># 匹配任意数量的空格</em><br>pattern = "\s*"<br>string = " Hello World!"<br>match = re.match(pattern, string)<br>print(match.group()) <em># 输出: ' '</em>
4. 范围匹配
- 使用
1-
定义一个范围内的字符。
1 <em># 匹配小写字母a到e</em><br>pattern = "[a-e]"<br>string = "abcdeABCDE"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['a', 'b', 'c', 'd', 'e']</em>
5. 排除字符
- 使用
1^
排除某些字符。
1 <em># 匹配除了a到z之外的所有字符</em><br>pattern = "[^a-z]"<br>string = "123ABCdef"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['1', '2', '3', 'A', 'B', 'C']</em>
6. 字符集组合
- 可以将多个字符集组合起来使用。
1 <em># 匹配数字或大写字母</em><br>pattern = "[0-9A-Z]+"<br>string = "Hello123World"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['123']</em>
7. 位置锚定
-
1^
表示行首,
1$表示行尾。
1 <em># 匹配以大写字母开头的单词</em><br>pattern = "^[A-Z][a-zA-Z]*"<br>string = "Hello world"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['Hello']</em>
8. 分组与引用
- 使用圆括号
1()
来创建一个捕获组。
1 <em># 捕获日期格式</em><br>pattern = "(\d{4})-(\d{2})-(\d{2})"<br>string = "Today is 2023-04-01."<br>match = re.match(pattern, "2023-04-01")<br>if match:<br> year = match.group(1)<br> month = match.group(2)<br> day = match.group(3)<br> print(f"Year: {year}, Month: {month}, Day: {day}")
9. 非捕获组
- 如果不关心某部分的内容,可以使用
1(?:)
。
1 <em># 不捕获中间的冒号</em><br>pattern = r"(\d{2}):(?:\d{2}):\d{2}"<br>string = "09:30:15"<br>match = re.match(pattern, string)<br>if match:<br> hour = match.group(1)<br> print(hour) <em># 输出: 09</em>
10. 替换文本
- 使用
1re.sub()
方法替换字符串中的匹配项。
1 <em># 将所有空格替换成下划线</em><br>pattern = "\s+"<br>string = "Hello World"<br>new_string = re.sub(pattern, "_", string)<br>print(new_string) <em># 输出: Hello_World</em>
11. 贪婪与非贪婪匹配
- 贪婪匹配:默认情况下,正则表达式会尽可能多地匹配字符。
- 非贪婪匹配:使用
1?
使匹配变得“懒惰”,即尽可能少地匹配字符。
1 <em># 贪婪匹配</em><br>pattern = "<.*>"<br>string = "<p>Hello <span>World</span></p>"<br>match = re.search(pattern, string)<br>print(match.group()) <em># 输出: <p>Hello <span>World</span></p></em><br><br><em># 非贪婪匹配</em><br>pattern = "<.*?>"<br>string = "<p>Hello <span>World</span></p>"<br>match = re.search(pattern, string)<br>print(match.group()) <em># 输出: <p></em>
12. 条件分支
- 使用
1(?P<name>)
命名捕获组,并通过
1(?P=name)引用它们。
1 <em># 匹配重复的单词</em><br>pattern = r"\b(\w+)\b\s+\1\b"<br>string = "hello hello world"<br>match = re.sub(pattern, r"\1", string, flags=re.IGNORECASE)<br>print(match) <em># 输出: hello world</em>
13. 重复限定符
- 使用
1{n}
指定精确重复次数。
- 使用
1{n,}
指定至少重复n次。
- 使用
1{n,m}
指定重复n到m次。
1 <em># 匹配恰好重复三次的字符</em><br>pattern = r"a{3}"<br>string = "aaabbbccc"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: []</em><br><br><em># 匹配至少重复两次的字符</em><br>pattern = r"a{2,}"<br>string = "aaabbbccc"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['aaa']</em><br><br><em># 匹配重复两到四次的字符</em><br>pattern = r"a{2,4}"<br>string = "aaabbbccc"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['aaa']</em>
14. 特殊字符
- 点号
1.
:匹配除换行符之外的任何字符。
- 反斜杠
1\
:转义特殊字符。
1 <em># 匹配包含任何字符的单词</em><br>pattern = r"\w+"<br>string = "hello\nworld"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['hello']</em><br><br><em># 匹配特殊字符</em><br>pattern = r"\."<br>string = "hello.world"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['.']</em>
15. 边界限定符
- 单词边界
1\b
:匹配单词的开始和结束。
- 非单词边界
1\B
:匹配非单词的位置。
1 <em># 匹配单词边界</em><br>pattern = r"\bhello\b"<br>string = "hello world"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['hello']</em><br><br><em># 匹配非单词边界</em><br>pattern = r"\Bworld\B"<br>string = "hello world"<br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: []</em>
16. 标志位
- 忽略大小写
1re.IGNORECASE
:使匹配不区分大小写。
- 多行模式
1re.MULTILINE
:使
1^和
1$分别匹配每一行的开始和结束。
- 点号匹配换行符
1re.DOTALL
:使
1.匹配包括换行符在内的任何字符。
1 <em># 忽略大小写</em><br>pattern = r"hello"<br>string = "Hello world"<br>matches = re.findall(pattern, string, re.IGNORECASE)<br>print(matches) <em># 输出: ['Hello']</em><br><br><em># 多行模式</em><br>pattern = r"^hello"<br>string = "hello\nworld"<br>matches = re.findall(pattern, string, re.MULTILINE)<br>print(matches) <em># 输出: ['hello']</em><br><br><em># 点号匹配换行符</em><br>pattern = r"hello.*world"<br>string = "hello\nworld"<br>matches = re.findall(pattern, string, re.DOTALL)<br>print(matches) <em># 输出: ['hello\nworld']</em>
实战案例分析
假设我们需要从一段文本中提取所有的邮箱地址。这可以通过正则表达式轻松实现。邮箱地址的一般形式为
1 | username@domain.com |
。下面是一个简单的示例:
1 <em># 提取邮箱地址</em><br>pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"<br>string = """<br>John Doe <johndoe@example.com><br>Jane Smith <janesmith@company.org><br>"""<br><br>matches = re.findall(pattern, string)<br>print(matches) <em># 输出: ['johndoe@example.com', 'janesmith@company.org']</em>