活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

掌握正则表达式核心技巧轻松应对各种复杂数据处理任务显著提升工作效率的实用指南

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-3 13:40:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

正则表达式(Regular Expression,简称regex或regexp)是一种强大而灵活的文本处理工具,它使用特定的字符序列来描述和匹配字符串模式。在当今数据爆炸的时代,无论是数据清洗、日志分析、信息提取还是表单验证,正则表达式都能提供高效而优雅的解决方案。掌握正则表达式不仅能显著提升你的工作效率,还能让你在面对复杂数据处理任务时游刃有余。本文将带你深入了解正则表达式的核心技巧,帮助你从入门到精通,轻松应对各种文本处理挑战。

正则表达式基础

什么是正则表达式

正则表达式是一种用于描述字符串模式的特殊语法。它由普通字符(如字母、数字)和特殊字符(称为”元字符”)组成,可以用来检查一个字符串是否含有某种模式、替换匹配的子串或提取符合条件的子串。

基本语法

最简单的正则表达式就是普通字符串,它精确匹配自身:
  1. import re
  2. pattern = "hello"
  3. text = "hello world"
  4. result = re.search(pattern, text)
  5. print(result.group())  # 输出: hello
复制代码

元字符是正则表达式中具有特殊含义的字符:

• .: 匹配除换行符以外的任意字符
• \d: 匹配任意数字,等价于[0-9]
• \D: 匹配任意非数字字符
• \w: 匹配字母、数字和下划线,等价于[a-zA-Z0-9_]
• \W: 匹配非字母、数字和下划线
• \s: 匹配任意空白字符(空格、制表符、换行符等)
• \S: 匹配任意非空白字符
  1. import re
  2. # 匹配任意字符
  3. pattern = "h.llo"
  4. text = "hallo world"
  5. result = re.search(pattern, text)
  6. print(result.group())  # 输出: hallo
  7. # 匹配数字
  8. pattern = "\d+"
  9. text = "I have 2 apples and 5 oranges"
  10. result = re.findall(pattern, text)
  11. print(result)  # 输出: ['2', '5']
复制代码

量词用于指定前面的字符或模式出现的次数:

• *: 零次或多次
• +: 一次或多次
• ?: 零次或一次
• {n}: 恰好n次
• {n,}: 至少n次
• {n,m}: 至少n次,至多m次
  1. import re
  2. # 匹配零次或多次
  3. pattern = "ab*c"
  4. text = "ac abc abbc abbbc"
  5. result = re.findall(pattern, text)
  6. print(result)  # 输出: ['ac', 'abc', 'abbc', 'abbbc']
  7. # 匹配一次或多次
  8. pattern = "ab+c"
  9. text = "ac abc abbc abbbc"
  10. result = re.findall(pattern, text)
  11. print(result)  # 输出: ['abc', 'abbc', 'abbbc']
  12. # 匹配恰好2次
  13. pattern = "ab{2}c"
  14. text = "abc abbc abbbc"
  15. result = re.findall(pattern, text)
  16. print(result)  # 输出: ['abbc']
复制代码

字符类用于匹配一组字符中的一个:

• [abc]: 匹配a、b或c中的任意一个
• [^abc]: 匹配除a、b、c以外的任意字符
• [a-z]: 匹配a到z之间的任意小写字母
• [A-Z]: 匹配A到Z之间的任意大写字母
• [0-9]: 匹配0到9之间的任意数字
  1. import re
  2. # 匹配字符类中的任意一个
  3. pattern = "[aeiou]"
  4. text = "hello world"
  5. result = re.findall(pattern, text)
  6. print(result)  # 输出: ['e', 'o', 'o']
  7. # 匹配不在字符类中的任意字符
  8. pattern = "[^aeiou]"
  9. text = "hello world"
  10. result = re.findall(pattern, text)
  11. print(result)  # 输出: ['h', 'l', 'l', ' ', 'w', 'r', 'l', 'd']
复制代码

使用括号()可以创建分组,分组可以用于:

1. 应用量词到一个子表达式
2. 限制选择范围
3. 捕获匹配的文本以便后续引用
  1. import re
  2. # 对子表达式应用量词
  3. pattern = "(ab)+"
  4. text = "ab abab ababab"
  5. result = re.findall(pattern, text)
  6. print(result)  # 输出: ['ab', 'ab', 'ab']
  7. # 捕获匹配的文本
  8. pattern = "(\d{4})-(\d{2})-(\d{2})"
  9. text = "Date: 2023-05-15"
  10. result = re.search(pattern, text)
  11. if result:
  12.     print("Full match:", result.group(0))  # 输出: Full match: 2023-05-15
  13.     print("Year:", result.group(1))       # 输出: Year: 2023
  14.     print("Month:", result.group(2))      # 输出: Month: 05
  15.     print("Day:", result.group(3))        # 输出: Day: 15
复制代码

边界匹配用于指定匹配的位置:

• ^: 匹配字符串的开始
• $: 匹配字符串的结束
• \b: 匹配单词边界
• \B: 匹配非单词边界
  1. import re
  2. # 匹配字符串开始
  3. pattern = "^hello"
  4. text = "hello world"
  5. result = re.search(pattern, text)
  6. print(result.group())  # 输出: hello
  7. # 匹配字符串结束
  8. pattern = "world$"
  9. text = "hello world"
  10. result = re.search(pattern, text)
  11. print(result.group())  # 输出: world
  12. # 匹配单词边界
  13. pattern = "\bhello\b"
  14. text = "hello world helloworld"
  15. result = re.findall(pattern, text)
  16. print(result)  # 输出: ['hello']
复制代码

使用|可以指定多个可能的匹配模式:
  1. import re
  2. # 匹配多个可能的模式
  3. pattern = "cat|dog"
  4. text = "I have a cat and a dog"
  5. result = re.findall(pattern, text)
  6. print(result)  # 输出: ['cat', 'dog']
复制代码

常用正则表达式模式与技巧

邮箱验证

邮箱验证是正则表达式的常见应用场景之一。一个基本的邮箱验证正则表达式如下:
  1. import re
  2. # 基本邮箱验证
  3. pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
  4. emails = [
  5.     "user@example.com",
  6.     "user.name@example.co.uk",
  7.     "user-name@example.org",
  8.     "invalid.email",
  9.     "@example.com",
  10.     "user@.com"
  11. ]
  12. for email in emails:
  13.     if re.match(pattern, email):
  14.         print(f"{email} 是有效的邮箱地址")
  15.     else:
  16.         print(f"{email} 不是有效的邮箱地址")
复制代码

输出:
  1. user@example.com 是有效的邮箱地址
  2. user.name@example.co.uk 是有效的邮箱地址
  3. user-name@example.org 是有效的邮箱地址
  4. invalid.email 不是有效的邮箱地址
  5. @example.com 不是有效的邮箱地址
  6. user@.com 不是有效的邮箱地址
复制代码

电话号码验证

电话号码的格式因国家/地区而异,以下是一些常见的电话号码验证模式:
  1. import re
  2. # 美国电话号码验证
  3. us_phone_pattern = r"\(\d{3}\)\s\d{3}-\d{4}|\d{3}-\d{3}-\d{4}"
  4. us_phones = [
  5.     "(123) 456-7890",
  6.     "123-456-7890",
  7.     "123 456 7890",
  8.     "123.456.7890"
  9. ]
  10. for phone in us_phones:
  11.     if re.match(us_phone_pattern, phone):
  12.         print(f"{phone} 是有效的美国电话号码")
  13.     else:
  14.         print(f"{phone} 不是有效的美国电话号码")
  15. # 中国手机号码验证
  16. cn_phone_pattern = r"1[3-9]\d{9}"
  17. cn_phones = [
  18.     "13812345678",
  19.     "15987654321",
  20.     "12345678901",
  21.     "1891234567"
  22. ]
  23. for phone in cn_phones:
  24.     if re.match(cn_phone_pattern, phone):
  25.         print(f"{phone} 是有效的中国手机号码")
  26.     else:
  27.         print(f"{phone} 不是有效的中国手机号码")
复制代码

URL解析

解析URL并提取其中的各个部分:
  1. import re
  2. url_pattern = r"(https?|ftp)://([^/\r\n]+)(/[^\s]*)?"
  3. url = "https://www.example.com/path/to/page?query=param#fragment"
  4. match = re.match(url_pattern, url)
  5. if match:
  6.     protocol = match.group(1)
  7.     domain = match.group(2)
  8.     path = match.group(3)
  9.    
  10.     print(f"协议: {protocol}")
  11.     print(f"域名: {domain}")
  12.     print(f"路径: {path}")
复制代码

输出:
  1. 协议: https
  2. 域名: www.example.com
  3. 路径: /path/to/page?query=param#fragment
复制代码

HTML标签处理

提取或处理HTML标签:
  1. import re
  2. # 提取HTML标签内容
  3. html = "<div class='example'><p>Hello <span>world</span></p></div>"
  4. tag_pattern = r"<([^>]+)>(.*?)</\1>"
  5. def find_html_tags(html):
  6.     matches = re.finditer(tag_pattern, html, re.DOTALL)
  7.     for match in matches:
  8.         tag_name = match.group(1)
  9.         content = match.group(2)
  10.         print(f"标签: {tag_name}, 内容: {content}")
  11.         # 递归查找嵌套标签
  12.         find_html_tags(content)
  13. find_html_tags(html)
复制代码

输出:
  1. 标签: div, 内容: <p>Hello <span>world</span></p>
  2. 标签: p, 内容: Hello <span>world</span>
  3. 标签: span, 内容: world
复制代码

日期格式匹配

匹配不同格式的日期:
  1. import re
  2. # 匹配多种日期格式
  3. date_pattern = r"(\d{4})[-/](\d{1,2})[-/](\d{1,2})|(\d{1,2})[-/](\d{1,2})[-/](\d{4})"
  4. dates = [
  5.     "2023-05-15",
  6.     "05/15/2023",
  7.     "2023/5/15",
  8.     "15-05-2023"
  9. ]
  10. for date in dates:
  11.     match = re.match(date_pattern, date)
  12.     if match:
  13.         if match.group(1):  # YYYY-MM-DD 或 YYYY/MM/DD 格式
  14.             year, month, day = match.group(1), match.group(2), match.group(3)
  15.         else:  # MM-DD-YYYY 或 DD-MM-YYYY 格式
  16.             month_or_day, day_or_month, year = match.group(4), match.group(5), match.group(6)
  17.             # 假设第一个数字大于12,则为DD-MM-YYYY格式
  18.             if int(month_or_day) > 12:
  19.                 day, month = month_or_day, day_or_month
  20.             else:
  21.                 month, day = month_or_day, day_or_month
  22.         
  23.         print(f"日期: {date}, 解析为: {year}年{month}月{day}日")
复制代码

密码强度验证

验证密码强度,通常要求包含大小写字母、数字和特殊字符:
  1. import re
  2. def check_password_strength(password):
  3.     # 至少8个字符
  4.     if len(password) < 8:
  5.         return "弱:密码长度至少为8个字符"
  6.    
  7.     # 包含大写字母
  8.     if not re.search(r"[A-Z]", password):
  9.         return "弱:密码必须包含至少一个大写字母"
  10.    
  11.     # 包含小写字母
  12.     if not re.search(r"[a-z]", password):
  13.         return "弱:密码必须包含至少一个小写字母"
  14.    
  15.     # 包含数字
  16.     if not re.search(r"\d", password):
  17.         return "弱:密码必须包含至少一个数字"
  18.    
  19.     # 包含特殊字符
  20.     if not re.search(r"[!@#$%^&*(),.?":{}|<>]", password):
  21.         return "中:建议包含特殊字符以增强安全性"
  22.    
  23.     return "强:密码符合所有安全要求"
  24. passwords = [
  25.     "password",
  26.     "Password",
  27.     "Password123",
  28.     "Password123!",
  29.     "P@ssw0rd"
  30. ]
  31. for pwd in passwords:
  32.     print(f"密码 '{pwd}': {check_password_strength(pwd)}")
复制代码

正则表达式在不同编程语言中的应用

Python中的正则表达式

Python通过re模块提供正则表达式支持:
  1. import re
  2. # re.match: 从字符串开头匹配
  3. pattern = r"\d+"
  4. text = "123 abc 456"
  5. result = re.match(pattern, text)
  6. if result:
  7.     print("match:", result.group())  # 输出: match: 123
  8. # re.search: 在整个字符串中搜索第一个匹配
  9. result = re.search(pattern, text)
  10. if result:
  11.     print("search:", result.group())  # 输出: search: 123
  12. # re.findall: 查找所有匹配
  13. result = re.findall(pattern, text)
  14. print("findall:", result)  # 输出: findall: ['123', '456']
  15. # re.finditer: 返回一个迭代器,包含所有匹配对象
  16. for match in re.finditer(pattern, text):
  17.     print(f"finditer: {match.group()} at position {match.span()}")
  18. # re.sub: 替换匹配的子串
  19. result = re.sub(pattern, "NUM", text)
  20. print("sub:", result)  # 输出: sub: NUM abc NUM
  21. # re.split: 根据匹配分割字符串
  22. result = re.split(r"\s+", text)
  23. print("split:", result)  # 输出: split: ['123', 'abc', '456']
  24. # 编译正则表达式
  25. compiled_pattern = re.compile(r"\d+")
  26. result = compiled_pattern.findall(text)
  27. print("compiled:", result)  # 输出: compiled: ['123', '456']
复制代码

JavaScript中的正则表达式

JavaScript通过RegExp对象提供正则表达式支持:
  1. // 创建正则表达式
  2. const pattern1 = /\d+/g;  // 字面量方式
  3. const pattern2 = new RegExp("\\d+", "g");  // 构造函数方式
  4. const text = "123 abc 456";
  5. // test(): 测试是否匹配
  6. console.log(pattern1.test(text));  // 输出: true
  7. // exec(): 执行匹配,返回匹配结果
  8. let result;
  9. while ((result = pattern1.exec(text)) !== null) {
  10.     console.log(`exec: ${result[0]} at position ${result.index}`);
  11. }
  12. // match(): 字符串方法,返回匹配结果
  13. const matches = text.match(/\d+/g);
  14. console.log("match:", matches);  // 输出: match: ['123', '456']
  15. // search(): 字符串方法,返回匹配位置
  16. const position = text.search(/\d+/);
  17. console.log("search:", position);  // 输出: search: 0
  18. // replace(): 字符串方法,替换匹配的子串
  19. const replaced = text.replace(/\d+/g, "NUM");
  20. console.log("replace:", replaced);  // 输出: replace: NUM abc NUM
  21. // split(): 字符串方法,根据匹配分割字符串
  22. const parts = text.split(/\s+/);
  23. console.log("split:", parts);  // 输出: split: ['123', 'abc', '456']
复制代码

Java中的正则表达式

Java通过java.util.regex包提供正则表达式支持:
  1. import java.util.regex.*;
  2. public class RegexExample {
  3.     public static void main(String[] args) {
  4.         String text = "123 abc 456";
  5.         
  6.         // Pattern和Matcher
  7.         Pattern pattern = Pattern.compile("\\d+");
  8.         Matcher matcher = pattern.matcher(text);
  9.         
  10.         // find(): 查找下一个匹配
  11.         while (matcher.find()) {
  12.             System.out.println("find: " + matcher.group() + " at position " + matcher.start());
  13.         }
  14.         
  15.         // matches(): 尝试将整个区域与模式匹配
  16.         matcher.reset();
  17.         System.out.println("matches: " + matcher.matches());  // 输出: matches: false
  18.         
  19.         // lookingAt(): 尝试从区域开头开始匹配
  20.         matcher.reset();
  21.         System.out.println("lookingAt: " + matcher.lookingAt());  // 输出: lookingAt: true
  22.         
  23.         // String类的正则方法
  24.         String[] parts = text.split("\\s+");
  25.         System.out.println("split: " + Arrays.toString(parts));  // 输出: split: [123, abc, 456]
  26.         
  27.         String replaced = text.replaceAll("\\d+", "NUM");
  28.         System.out.println("replaceAll: " + replaced);  // 输出: replaceAll: NUM abc NUM
  29.         
  30.         boolean matches = text.matches("\\d+.*");
  31.         System.out.println("String.matches(): " + matches);  // 输出: String.matches(): true
  32.     }
  33. }
复制代码

实际案例分析

数据清洗和转换

假设我们有一份包含用户信息的原始数据,需要从中提取并格式化:
  1. import re
  2. # 原始数据
  3. raw_data = """
  4. Name: John Doe, Age: 30, Email: john.doe@example.com
  5. Name: Jane Smith, Age: 25, Email: jane.smith@test.org
  6. Name: Bob Johnson, Age: 42, Email: bob.johnson@demo.net
  7. """
  8. # 提取并格式化数据
  9. pattern = r"Name: ([^,]+), Age: (\d+), Email: ([^\s]+)"
  10. formatted_data = []
  11. for line in raw_data.strip().split('\n'):
  12.     match = re.search(pattern, line)
  13.     if match:
  14.         name = match.group(1)
  15.         age = match.group(2)
  16.         email = match.group(3)
  17.         formatted_data.append(f"{name} ({age} years old) can be contacted at {email}")
  18. # 输出格式化后的数据
  19. for entry in formatted_data:
  20.     print(entry)
复制代码

输出:
  1. John Doe (30 years old) can be contacted at john.doe@example.com
  2. Jane Smith (25 years old) can be contacted at jane.smith@test.org
  3. Bob Johnson (42 years old) can be contacted at bob.johnson@demo.net
复制代码

日志文件分析

分析Web服务器日志,提取关键信息:
  1. import re
  2. from collections import Counter
  3. # 示例日志数据
  4. log_data = """
  5. 127.0.0.1 - - [10/Oct/2023:13:55:36 -0700] "GET /index.html HTTP/1.1" 200 2326
  6. 192.168.1.1 - - [10/Oct/2023:13:56:12 -0700] "GET /about.html HTTP/1.1" 200 3548
  7. 10.0.0.1 - - [10/Oct/2023:13:57:05 -0700] "GET /contact.html HTTP/1.1" 200 1876
  8. 127.0.0.1 - - [10/Oct/2023:13:58:22 -0700] "GET /index.html HTTP/1.1" 200 2326
  9. 192.168.1.1 - - [10/Oct/2023:13:59:15 -0700] "POST /submit-form HTTP/1.1" 302 0
  10. 10.0.0.1 - - [10/Oct/2023:14:00:33 -0700] "GET /products.html HTTP/1.1" 404 512
  11. """
  12. # 日志解析模式
  13. log_pattern = r'(\d+\.\d+\.\d+\.\d+).*?\[(.*?)\].*?"(GET|POST) (.*?) HTTP/.*?" (\d+) (\d+)'
  14. ips = []
  15. status_codes = []
  16. pages = []
  17. for line in log_data.strip().split('\n'):
  18.     match = re.search(log_pattern, line)
  19.     if match:
  20.         ip = match.group(1)
  21.         timestamp = match.group(2)
  22.         method = match.group(3)
  23.         page = match.group(4)
  24.         status_code = match.group(5)
  25.         size = match.group(6)
  26.         
  27.         ips.append(ip)
  28.         status_codes.append(status_code)
  29.         pages.append(page)
  30. # 统计IP访问次数
  31. ip_counter = Counter(ips)
  32. print("Top IP addresses:")
  33. for ip, count in ip_counter.most_common():
  34.     print(f"{ip}: {count} requests")
  35. # 统计状态码
  36. status_counter = Counter(status_codes)
  37. print("\nStatus code distribution:")
  38. for status, count in status_counter.items():
  39.     print(f"{status}: {count} responses")
  40. # 统计访问最多的页面
  41. page_counter = Counter(pages)
  42. print("\nMost requested pages:")
  43. for page, count in page_counter.most_common():
  44.     print(f"{page}: {count} requests")
复制代码

输出:
  1. Top IP addresses:
  2. 127.0.0.1: 2 requests
  3. 192.168.1.1: 2 requests
  4. 10.0.0.1: 2 requests
  5. Status code distribution:
  6. 200: 4 responses
  7. 302: 1 responses
  8. 404: 1 responses
  9. Most requested pages:
  10. /index.html: 2 requests
  11. /about.html: 1 requests
  12. /contact.html: 1 requests
  13. /submit-form: 1 requests
  14. /products.html: 1 requests
复制代码

Web Scraping

从HTML中提取特定信息:
  1. import re
  2. # 示例HTML内容
  3. html = """
  4. <html>
  5. <head>
  6.     <title>Example Page</title>
  7. </head>
  8. <body>
  9.     <h1>Welcome to the Example Page</h1>
  10.     <div class="content">
  11.         <p>This is the first paragraph.</p>
  12.         <p>This is the second paragraph with <a href="https://example.com/link1">a link</a>.</p>
  13.         <ul>
  14.             <li>Item 1</li>
  15.             <li>Item 2</li>
  16.             <li>Item 3</li>
  17.         </ul>
  18.     </div>
  19.     <div class="footer">
  20.         <p>Copyright © 2023 Example Company</p>
  21.     </div>
  22. </body>
  23. </html>
  24. """
  25. # 提取标题
  26. title_pattern = r"<title>(.*?)</title>"
  27. title_match = re.search(title_pattern, html)
  28. if title_match:
  29.     print("Page title:", title_match.group(1))
  30. # 提取所有段落
  31. paragraph_pattern = r"<p>(.*?)</p>"
  32. paragraphs = re.findall(paragraph_pattern, html)
  33. print("\nParagraphs:")
  34. for i, p in enumerate(paragraphs, 1):
  35.     print(f"{i}. {p}")
  36. # 提取所有链接
  37. link_pattern = r"<a href="(.*?)">.*?</a>"
  38. links = re.findall(link_pattern, html)
  39. print("\nLinks:")
  40. for link in links:
  41.     print(f"- {link}")
  42. # 提取列表项
  43. list_pattern = r"<li>(.*?)</li>"
  44. list_items = re.findall(list_pattern, html)
  45. print("\nList items:")
  46. for i, item in enumerate(list_items, 1):
  47.     print(f"{i}. {item}")
复制代码

输出:
  1. Page title: Example Page
  2. Paragraphs:
  3. 1. This is the first paragraph.
  4. 2. This is the second paragraph with a link.
  5. 3. Copyright © 2023 Example Company
  6. Links:
  7. - https://example.com/link1
  8. List items:
  9. 1. Item 1
  10. 2. Item 2
  11. 3. Item 3
复制代码

文本替换和格式化

批量替换和格式化文本:
  1. import re
  2. # 原始文本
  3. text = """
  4. In the year 2023, the company revenue was $1,234,567.89.
  5. By 2024, it is expected to reach $1,500,000.00.
  6. Contact us at info@example.com or support@example.org for more information.
  7. """
  8. # 格式化日期
  9. formatted_text = re.sub(r"\b(\d{4})\b", r"Year \1", text)
  10. print("Formatted dates:")
  11. print(formatted_text)
  12. # 格式化货币
  13. formatted_text = re.sub(r"\$([0-9,]+\.\d{2})", r"USD \1", formatted_text)
  14. print("\nFormatted currency:")
  15. print(formatted_text)
  16. # 隐藏邮箱地址
  17. formatted_text = re.sub(r"(\w+)@(\w+\.\w+)", r"\1 at \2", formatted_text)
  18. print("\nObfuscated emails:")
  19. print(formatted_text)
  20. # 提取所有数字
  21. numbers = re.findall(r"\b\d+(?:,\d+)*(?:\.\d+)?\b", text)
  22. print("\nExtracted numbers:")
  23. for num in numbers:
  24.     print(f"- {num}")
复制代码

输出:
  1. Formatted dates:
  2. In the Year 2023, the company revenue was $1,234,567.89.
  3. By Year 2024, it is expected to reach $1,500,000.00.
  4. Contact us at info@example.com or support@example.org for more information.
  5. Formatted currency:
  6. In the Year 2023, the company revenue was USD 1,234,567.89.
  7. By Year 2024, it is expected to reach USD 1,500,000.00.
  8. Contact us at info@example.com or support@example.org for more information.
  9. Obfuscated emails:
  10. In the Year 2023, the company revenue was USD 1,234,567.89.
  11. By Year 2024, it is expected to reach USD 1,500,000.00.
  12. Contact us at info at example.com or support at example.org for more information.
  13. Extracted numbers:
  14. - 2023
  15. - 1,234,567.89
  16. - 2024
  17. - 1,500,000.00
复制代码

性能优化与最佳实践

避免贪婪匹配

默认情况下,量词是贪婪的,会尽可能多地匹配字符。这可能导致性能问题或意外的匹配结果。使用非贪婪量词(在量词后加?)可以避免这个问题:
  1. import re
  2. # 贪婪匹配示例
  3. html = "<div>Content 1</div><div>Content 2</div>"
  4. greedy_pattern = r"<div>.*</div>"
  5. greedy_match = re.search(greedy_pattern, html)
  6. print("Greedy match:", greedy_match.group(0))  # 匹配整个字符串
  7. # 非贪婪匹配示例
  8. non_greedy_pattern = r"<div>.*?</div>"
  9. non_greedy_match = re.search(non_greedy_pattern, html)
  10. print("Non-greedy match:", non_greedy_match.group(0))  # 只匹配第一个div
复制代码

输出:
  1. Greedy match: <div>Content 1</div><div>Content 2</div>
  2. Non-greedy match: <div>Content 1</div>
复制代码

使用非捕获组

当只需要分组而不需要捕获匹配的文本时,使用非捕获组(?:...)可以提高性能:
  1. import re
  2. # 使用捕获组
  3. capturing_pattern = r"(ab|cd)+"
  4. text = "ab cd abcd"
  5. result = re.findall(capturing_pattern, text)
  6. print("Capturing groups:", result)  # 输出: ['ab', 'cd', 'ab']
  7. # 使用非捕获组
  8. non_capturing_pattern = r"(?:ab|cd)+"
  9. result = re.findall(non_capturing_pattern, text)
  10. print("Non-capturing groups:", result)  # 输出: ['ab', 'cd', 'abcd']
复制代码

预编译正则表达式

如果多次使用同一个正则表达式,预编译它可以提高性能:
  1. import re
  2. import time
  3. # 不预编译
  4. text = "The quick brown fox jumps over the lazy dog. " * 1000
  5. pattern = r"\b\w{3}\b"
  6. start_time = time.time()
  7. for _ in range(1000):
  8.     re.findall(pattern, text)
  9. end_time = time.time()
  10. print(f"Without compilation: {end_time - start_time:.4f} seconds")
  11. # 预编译
  12. compiled_pattern = re.compile(r"\b\w{3}\b")
  13. start_time = time.time()
  14. for _ in range(1000):
  15.     compiled_pattern.findall(text)
  16. end_time = time.time()
  17. print(f"With compilation: {end_time - start_time:.4f} seconds")
复制代码

避免回溯问题

复杂的正则表达式可能导致大量的回溯,影响性能。以下是一些避免回溯问题的技巧:

1. 使用更具体的字符类而不是.
  1. import re
  2. # 低效模式:使用点号
  3. inefficient_pattern = r"<div>.*?</div>"
  4. html = "<div>Content 1</div><div>Content 2</div>"
  5. # 高效模式:使用更具体的字符类
  6. efficient_pattern = r"<div>[^<]*?</div>"
  7. # 测试性能
  8. import timeit
  9. inefficient_time = timeit.timeit(lambda: re.findall(inefficient_pattern, html), number=10000)
  10. efficient_time = timeit.timeit(lambda: re.findall(efficient_pattern, html), number=10000)
  11. print(f"Inefficient pattern: {inefficient_time:.4f} seconds")
  12. print(f"Efficient pattern: {efficient_time:.4f} seconds")
复制代码

1. 使用原子组或占有量词(如果支持)
  1. import regex  # 注意:这里使用第三方regex模块,支持更多特性
  2. # 使用原子组 (?>...)
  3. atomic_pattern = r"<div>(?>.*?)</div>"
  4. # 使用占有量词 *+, ++, ?+
  5. possessive_pattern = r"<div>.*+</div>"
  6. html = "<div>Content 1</div><div>Content 2</div>"
  7. print("Atomic group:", regex.findall(atomic_pattern, html))
  8. print("Possessive quantifier:", regex.findall(possessive_pattern, html))
复制代码

进阶技巧与资源推荐

断言(零宽断言)

断言用于匹配特定的位置,而不消耗字符。它们分为四种类型:

1. 正向先行断言(?=...):匹配后面的模式
2. 负向先行断言(?!...):匹配后面不是的模式
3. 正向后行断言(?<=...):匹配前面的模式
4. 负向后行断言(?<!...):匹配前面不是的模式
  1. import re
  2. # 正向先行断言:匹配后面跟着"fox"的单词
  3. text = "The quick brown fox jumps over the lazy dog"
  4. pattern = r"\w+(?= fox)"
  5. result = re.search(pattern, text)
  6. print("Positive lookahead:", result.group())  # 输出: brown
  7. # 负向先行断言:匹配后面不跟着"fox"的单词
  8. pattern = r"\w+(?! fox)"
  9. result = re.findall(pattern, text)
  10. print("Negative lookahead:", result)  # 输出: ['The', 'quick', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
  11. # 正向后行断言:匹配前面是"quick"的单词
  12. pattern = r"(?<=quick )\w+"
  13. result = re.search(pattern, text)
  14. print("Positive lookbehind:", result.group())  # 输出: brown
  15. # 负向后行断言:匹配前面不是"quick"的单词
  16. pattern = r"(?<!quick )\w+"
  17. result = re.findall(pattern, text)
  18. print("Negative lookbehind:", result)  # 输出: ['The', 'quick', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
复制代码

回溯引用

回溯引用允许你引用前面捕获的组:
  1. import re
  2. # 匹配重复的单词
  3. text = "hello hello world world test"
  4. pattern = r"\b(\w+)\s+\1\b"
  5. result = re.findall(pattern, text)
  6. print("Repeated words:", result)  # 输出: ['hello', 'world']
  7. # 匹配HTML标签(开始和结束标签相同)
  8. html = "<div>Content</div><p>Paragraph</p>"
  9. pattern = r"<([a-z]+)>.*?</\1>"
  10. result = re.findall(pattern, html, re.DOTALL)
  11. print("HTML tags:", result)  # 输出: ['div', 'p']
复制代码

条件匹配

某些正则表达式引擎支持条件匹配:
  1. import regex  # 使用第三方regex模块
  2. # 条件匹配:如果前面有数字,则匹配"number",否则匹配"word"
  3. text1 = "123 number"
  4. text2 = "abc word"
  5. pattern = r"(\d)?(?(1)number|word)"
  6. result1 = regex.search(pattern, text1)
  7. result2 = regex.search(pattern, text2)
  8. print("Text 1:", result1.group())  # 输出: number
  9. print("Text 2:", result2.group())  # 输出: word
复制代码

正则表达式调试工具

调试复杂的正则表达式可能很困难,以下是一些有用的工具:

1. Regex101(https://regex101.com/) - 在线正则表达式测试和调试工具
2. Debuggex(https://www.debuggex.com/) - 可视化正则表达式调试工具
3. RegExr(https://regexr.com/) - 在线正则表达式学习和测试工具

学习资源推荐

1. 书籍:《精通正则表达式》(Mastering Regular Expressions)- Jeffrey E.F. Friedl《正则表达式必知必会》(Regular Expressions Cookbook)- Jan Goyvaerts, Steven Levithan
2. 《精通正则表达式》(Mastering Regular Expressions)- Jeffrey E.F. Friedl
3. 《正则表达式必知必会》(Regular Expressions Cookbook)- Jan Goyvaerts, Steven Levithan
4. 在线教程:MDN Web Docs - 正则表达式 (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)RegexOne - 交互式正则表达式教程 (https://regexone.com/)Regular-Expressions.info - 正则表达式教程和参考 (https://www.regular-expressions.info/)
5. MDN Web Docs - 正则表达式 (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)
6. RegexOne - 交互式正则表达式教程 (https://regexone.com/)
7. Regular-Expressions.info - 正则表达式教程和参考 (https://www.regular-expressions.info/)
8. 练习平台:HackerRank - 正则表达式练习 (https://www.hackerrank.com/domains/regex)Codewars - 正则表达式挑战 (https://www.codewars.com/?language=python)
9. HackerRank - 正则表达式练习 (https://www.hackerrank.com/domains/regex)
10. Codewars - 正则表达式挑战 (https://www.codewars.com/?language=python)

书籍:

• 《精通正则表达式》(Mastering Regular Expressions)- Jeffrey E.F. Friedl
• 《正则表达式必知必会》(Regular Expressions Cookbook)- Jan Goyvaerts, Steven Levithan

在线教程:

• MDN Web Docs - 正则表达式 (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)
• RegexOne - 交互式正则表达式教程 (https://regexone.com/)
• Regular-Expressions.info - 正则表达式教程和参考 (https://www.regular-expressions.info/)

练习平台:

• HackerRank - 正则表达式练习 (https://www.hackerrank.com/domains/regex)
• Codewars - 正则表达式挑战 (https://www.codewars.com/?language=python)

总结

正则表达式是一种强大而灵活的文本处理工具,掌握它可以显著提升你的工作效率。本文从基础语法到高级技巧,全面介绍了正则表达式的核心概念和应用场景。通过学习和实践这些技巧,你将能够轻松应对各种复杂数据处理任务。

记住,正则表达式的学习是一个渐进的过程。开始时可能会觉得语法复杂,但随着实践的增加,你会逐渐熟悉并能够灵活运用它们。建议从简单的模式开始,逐步尝试更复杂的表达式,并利用在线工具进行测试和调试。

无论你是数据分析师、软件开发者还是系统管理员,正则表达式都将成为你工具箱中不可或缺的一部分。希望本文能够帮助你掌握正则表达式的核心技巧,并在实际工作中发挥其强大的威力。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则