前言
是一种用于描述、匹配和操作文本字符串的强大工具。你可以把它想象成一个 “字符串的过滤模式” 或 “高级的查找替换工具”。。
二、正则的优缺点
1.正则表达式的优点
极其强大和灵活
能够执行非常复杂和灵活的字符串匹配操作,这是普通的字符串查找(如indexof)完全无法比拟的。无论是“以a开头,以b结尾,中间不能有c”,还是“匹配所有第三个字符是数字的单词”,正则都能轻松描述。高度简洁
一个简短的正则表达式模式,往往可以替代几十行甚至上百行的传统字符串处理代码(如循环、判断、切片等)。这使得代码非常精简。标准化和通用性
正则表达式的语法在各种编程语言(如 javascript, python, java, c#, go 等)、文本编辑器(如 vs code, sublime text)和命令行工具(如grep,awk,sed)中基本都是通用的。学会一个,处处可用。执行效率高(对于复杂操作)
对于复杂的字符串匹配和验证任务,经过优化的正则引擎通常比用普通代码手动编写的同等功能要快得多。因为它是由底层c/c++等语言实现的高效算法。广泛应用于数据处理
是数据提取(爬虫)、数据清洗、日志分析、表单验证、文件批量重命名等任务的首选工具。
2.正则表达式的缺点
学习曲线陡峭,可读性差
这是正则表达式最大的缺点。对于初学者来说,一段复杂的正则表达式看起来就像是一堆“乱码”或“天书”,例如:/^(?=.*[a-z])(?=.*[a-z])(?=.*\d)[\w!@#$%^&*]{8,}$/。这使得代码的维护和调试变得困难。难以调试和维护
当一个复杂的正则表达式不能正常工作时,排查问题非常困难。你很难一眼看出到底是哪个部分写错了,或者为什么它没有匹配到你期望的内容。容易写得过于复杂和脆弱
开发者容易试图用一个“万能”的正则表达式去解决所有问题,导致模式变得极其复杂和难以理解。而且,一个微小的文本格式变化就可能让整个正则表达式失效。性能陷阱
虽然正则通常很快,但编写不当的正则表达式可能导致“灾难性回溯”,使得匹配时间呈指数级增长,甚至导致程序卡死。这在处理长字符串时尤为危险。并非万能
正则表达式是基于模式的,它不适合处理所有文本问题,特别是那些具有嵌套结构的文本。典型反例:解析 html/xml。由于标签可以无限嵌套(
<div><div><div>...</div></div></div>),使用正则表达式来正确解析是非常困难且不可靠的,应该使用专门的解析器(如 dom parser)。同理:处理复杂的数学表达式、json、编程语言等,这些有递归结构的内容,正则表达式难以胜任。
三、正则表达式 - 核心知识总结
一、 元字符 - 构建模式的“字母”
这些是拥有特殊含义的字符,是正则表达式的核心。
| 元字符 | 描述 | 示例 | 匹配示例 |
|---|---|---|---|
| . | 匹配任意单个字符(除换行符 \n 外) | a.c | abc, a c, a&c |
| \d | 匹配任意数字 | \d\d | 12, 00 |
| \d | 匹配任意非数字 | \d\d | ab, @# |
| \w | 匹配字母、数字、下划线 | \w\w | a1, b_ |
| \w | 匹配非字母、数字、下划线 | \w | @, , - |
| \s | 匹配任意空白符(空格、制表符、换行符) | a\sb | a b |
| \s | 匹配任意非空白符 | a\sb | a+b, aab |
| \b | 匹配单词的边界 | \bhello\b | hello world 中的 hello |
| \b | 匹配非单词边界 | \bhello\b | ahellob 中的 hello |
| ^ | 匹配字符串的开始(在多行模式下匹配行首) | ^hello | hello world 中的 hello |
| $ | 匹配字符串的结束(在多行模式下匹配行尾) | world$ | hello world 中的 world |
二、 量词 - 指定字符的数量
用于指定前面的字符或组出现的次数。
| 量词 | 描述 | 示例 | 匹配示例 |
|---|---|---|---|
| * | 匹配 0次 或 多次 | ab*c | ac, abc, abbc |
| + | 匹配 1次 或 多次 | ab+c | abc, abbc (不匹配 ac) |
| ? | 匹配 0次 或 1次 | colou?r | color, colour |
| {n} | 匹配恰好 n 次 | a{3} | aaa |
| {n,} | 匹配至少 n 次 | a{2,} | aa, aaa, ... |
| {n,m} | 匹配 n 到 m 次 | a{2,4} | aa, aaa, aaaa |
贪婪 vs 非贪婪(懒惰)
默认(贪婪):尽可能匹配更长的字符串。
a.+b在axxxbxxxb中会匹配整个字符串。非贪婪:在量词后加
?,匹配最短的字符串。a.+?b在axxxbxxxb中只匹配axxxb。
三、 字符集与分组 - 定义匹配范围
| 语法 | 描述 | 示例 | 匹配示例 |
|---|---|---|---|
| [abc] | 匹配 a, b, 或 c 中的任意一个字符 | [aeiou] | 匹配任何元音字母 |
| [a-z] | 匹配 a 到 z 范围内的任意字符 | [0-9] | 等同于 \d |
| [^abc] | 匹配任何不在 a, b, c 中的字符 | [^0-9] | 等同于 \d |
| (abc) | 捕获组,将多个字符视为一个单元,并可提取内容 | (ab)+ | ab, abab |
| (?:abc) | 非捕获组,只分组,不捕获内容 | (?:ab)+ | ab, abab (不捕获) |
| **` | `** | 或 操作,匹配左边或右边的模式 | `cat |
四、 零宽断言 - 匹配位置,而非字符
用于指定一个位置,这个位置需要满足某些条件,但不会消耗字符。
| 断言 | 描述 | 示例 | 匹配示例 |
|---|---|---|---|
| (?=exp) | 正向先行断言:匹配位置后面是 exp | windows(?=10|11) | windows10, windows11 中的 windows |
| (?!exp) | 负向先行断言:匹配位置后面不是 exp | windows(?!95|98) | windows10 中的 windows (排除 windows95) |
| (?<=exp) | 正向后行断言:匹配位置前面是 exp | (?<=\$)\d+ | $100 中的 100 |
| (?<!exp) | 负向后行断言:匹配位置前面不是 exp | (?<!\$)\d+ | €100 中的 100 (排除 $100) |
五、 实用案例集锦
匹配手机号(中国大陆)
/^1[3-9]\d{9}$/^字符串开始1以1开头[3-9]第二位是3-9\d{9}后面是9位数字$字符串结束
匹配邮箱
/^[a-za-z0-9._%+-]+@[a-za-z0-9.-]+\.[a-za-z]{2,}$/[a-za-z0-9._%+-]+用户名部分(至少一个字符)@字面量@[a-za-z0-9.-]+域名部分\.字面量.[a-za-z]{2,}顶级域名(2位以上字母)
匹配中文字符
/[\u4e00-\u9fa5]/
匹配 unicode 范围内的中文字符。
提取 html 标签内容
/<div[^>]*>(.*?)<\/div>/
使用非贪婪模式
.*?来匹配第一个闭合标签之前的内容。
强密码校验(至少8位,含大小写字母和数字)
/^(?=.*[a-z])(?=.*[a-z])(?=.*\d)[\w!@#$%^&*]{8,}$/(?=.*[a-z])断言后面必须有小写字母。(?=.*[a-z])断言后面必须有大写字母。(?=.*\d)断言后面必须有数字。[\w!@#$%^&*]{8,}匹配至少8位允许的字符。
匹配 ipv4 地址
/^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/精确匹配 0.0.0.0 到 255.255.255.255。
六、 在编程语言中的使用要点
javascript:
const regex = /pattern/flags; // 字面量形式 const regex2 = new regexp('pattern', 'flags'); // 构造函数 const result = regex.test(string); // 返回布尔值 const matches = string.match(regex); // 返回匹配结果数组 const newstring = string.replace(regex, replacement); // 替换python:
import re pattern = re.compile(r'pattern', flags) if pattern.match(string): # 从开头匹配 if pattern.search(string): # 搜索整个字符串 matches = pattern.findall(string) # 查找所有匹配 new_string = pattern.sub(replacement, string) # 替换
常用标志(flags):
i:忽略大小写。g:全局匹配(找到所有匹配,而非第一个)。m:多行模式(使^和$匹配每行的开头和结尾)。s:单行模式(使.也能匹配换行符)。
总结与建议
从简单开始:先掌握
\d,\w,.,*,+,?,[],()这些最常用的。理解贪婪:大部分匹配过多的问题都是贪婪模式引起的,记得用
?转为非贪婪。性能考虑:避免使用过于复杂的嵌套或回溯,对于复杂的文本解析,有时用传统字符串方法更合适。
到此这篇关于正则表达式基本用法及知识点总结的文章就介绍到这了,更多相关正则表达式基本用法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论