当前位置: 首页 > news >正文

正则入门到精通


![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ee791b6fb74b4f649bdba48efea7c7ee.png

一、正则表达式入门​

正则表达式本质上是一串字符序列,用于定义一个文本模式。通过这个模式,我们可以指定要匹配的文本特征。例如,如果你想匹配一个以 “abc” 开头的字符串,正则表达式可以写作 “^abc”,其中 “^” 表示匹配字符串的开头。​

(一)基本字符匹配​

在正则表达式中,普通字符(如字母、数字)通常表示它们自身。例如,正则表达式 “abc” 可以匹配文本中的 “abc” 序列。如果文本是 “abcdef”,那么 “abc” 会匹配成功;但如果文本是 “defabc”,那么匹配失败,因为正则表达式是从左到右进行匹配的。​

案例(JavaScript):​

const text1 = "abcdef";const regex1 = /abc/;​

console.log(regex1.test(text1)); // 输出: true​const text2 = "defabc";const regex2 = /abc/;​

console.log(regex2.test(text2)); // 输出: false​

在上述代码中,/abc/是一个正则表达式字面量,test方法用于测试给定的字符串是否包含匹配正则表达式的文本。​

(二)特殊字符​

正则表达式中有一些特殊字符,它们具有特殊的含义。例如:​

“.”(点号):匹配任意单个字符(除了换行符)。例如,“a.c” 可以匹配 “abc”、“adc” 等,但不能匹配 “ac”。​
”(星号):表示前面的字符可以出现零次或多次。例如,“abc” 可以匹配 “ac”、“abc”、“abbc” 等。​
“+”(加号):表示前面的字符至少出现一次。例如,“ab+c” 可以匹配 “abc”、“abbc” 等,但不能匹配 “ac”。​
“?”(问号):表示前面的字符可以出现零次或一次。例如,“ab?c” 可以匹配 “ac” 和 “abc”。​
”(脱字符):用于匹配字符串的开头。例如,“abc” 表示匹配以 “abc” 开头的字符串。​
“​

” 表示匹配以 “abc” 结尾的字符串。​

// “.”的案例​

const text3 = "a1c a2c a c";const regex3 = /a.c/;​

console.log(text3.match(regex3)); // 输出: ["a1c"],注意:match方法默认只返回第一个匹配结果​// “*”的案例​

const text4 = "ac abc abbc abbbc";const regex4 = /ab*c/;​

console.log(text4.match(regex4)); // 输出: ["abbbc"]​// “+”的案例​

const text5 = "abc abbc abbbc";const regex5 = /ab+c/;​

console.log(text5.match(regex5)); // 输出: ["abbbc"]​// “?”的案例​

const text6 = "ac abc";const regex6 = /ab?c/;​

console.log(text6.match(regex6)); // 输出: ["abc"]​// “^”的案例​

const text7 = ["abcdef", "defabc", "abc"];const regex7 = /^abc/;​

text7.forEach(str => {​

console.log(regex7.test(str));// 输出: true, false, true​

});​

​

// “$”的案例​

const text8 = ["abc", "defabc", "abcd"];const regex8 = /abc$/;​

text8.forEach(str => {​

console.log(regex8.test(str));// 输出: true, true, false​

});

在这些案例中,match方法用于在字符串中查找所有匹配正则表达式的子字符串,并返回一个数组。如果没有找到匹配项,则返回null。test方法则用于判断字符串是否与正则表达式匹配,返回true或false。​

(三)字符集​

字符集用于匹配一组特定的字符。例如,“[abc]” 可以匹配 “a”、“b” 或 “c”。字符集还可以使用范围表示法,如 “[a-z]” 表示匹配任意一个小写字母,“[0-9]” 表示匹配任意一个数字。​

// 匹配元音字母​

const text9 = "apple banana cherry";const regex9 = /[aeiou]/g;​

console.log(text9.match(regex9));// 输出: ["a", "e", "a", "a", "e"],这里的“g”标志表示全局匹配,即找到所有匹配项​// 匹配数字​

const text10 = "123abcABC";const regex10 = /[0-9]/g;​

console.log(text10.match(regex10)); // 输出: ["1", "2", "3"]​// 匹配字母​

const text11 = "123abcABC";const regex11 = /[a-zA-Z]/g;​

console.log(text11.match(regex11)); // 输出: ["a", "b", "c", "A", "B", "C"]​

在上述代码中,正则表达式中的 “g” 标志是非常重要的,它使得match方法能够返回所有匹配的结果,而不仅仅是第一个。​

(四)分组​

分组是通过圆括号 “()” 来实现的。它可以将多个字符组合在一起,作为一个整体进行匹配。例如,“(abc)+” 表示匹配一个或多个 “abc” 序列。​

const text12 = "abcabcabc abcab ab";const regex12 = /(abc)+/g;​

console.log(text12.match(regex12));// 输出: ["abcabcabc", "abcab"]​

在这个例子中,通过分组我们能够准确匹配由一个或多个 “abc” 序列组成的子字符串。​

二、正则表达式的进阶应用​

(一)匹配特定格式的文本​

正则表达式可以用来匹配各种特定格式的文本,如日期、电话号码、电子邮件地址等。例如,一个简单的电子邮件地址匹配正则表达式可以写作 “[a-zA-Z0-9_.±]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+”。这个表达式通过字符集和分组的方式,确保了电子邮件地址的基本格式。​

// 日期匹配​

const text13 = "今天是2023-10-15,明天是2023-10-16";const regex13 = /\d{4}-\d{2}-\d{2}/g;​

console.log(text13.match(regex13));// 输出: ["2023-10-15", "2023-10-16"]​// 电话号码匹配​

const text14 = "联系电话:13800138000";const regex14 = /1\d{10}/;​

console.log(text14.match(regex14)); // 输出: ["13800138000"]​// 电子邮件地址匹配​

const text15 = "我的邮箱是example@example.com,另一个是test_123@test-company.co.uk";const regex15 = /[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+/g;​

console.log(text15.match(regex15));// 输出: ["example@example.com", "test_123@test-company.co.uk"]​

这些案例展示了如何使用正则表达式在 JavaScript 中准确匹配常见的特定格式文本。​

(二)捕获与替换​

正则表达式不仅可以用于匹配文本,还可以用于捕获和替换文本。通过分组和捕获功能,我们可以提取文本中的特定部分,并进行替换操作。例如,在文本编辑器中,我们可以使用正则表达式查找所有以 “http://” 开头的链接,并将其替换为 “https://”。​

// 捕获域名部分并替换链接协议​

const text16 = "请访问链接:http://example.com和http://test.com";const regex16 = /http://([a-zA-Z0-9-.]+)/g;const newText16 = text16.replace(regex16, "https://$1");​

console.log(newText16);// 输出: 请访问链接:https://example.com和https://test.com​// 提取价格部分​

const text17 = "苹果价格是10元,香蕉价格是5元";const regex17 = /价格是 (\d+) 元/g;const prices = text17.match(regex17);if (prices) {​

prices.forEach(price => {const num = price.match(/\d+/)[0];​

console.log(parseInt(num));// 输出: 10, 5​

});}

在第一个替换案例中,replace方法接受一个正则表达式和一个替换字符串,其中 “$1” 表示引用第一个捕获组的内容。在第二个提取案例中,我们先通过正则表达式找到包含价格的子字符串,然后再进一步提取其中的数字。​

(三)贪婪与非贪婪匹配​

在正则表达式中,贪婪模式会尽可能多地匹配字符,而非贪婪模式则会尽可能少地匹配字符。例如,“ab” 是一个贪婪模式,它会匹配 “aabb” 中的 “aabb”;而 “a?b” 是一个非贪婪模式,它会匹配 “aabb” 中的 “ab” 和 “abb”。​

// 贪婪模式案例​

const text18 = "aaaab";const regex18 = /a*b/;​

console.log(text18.match(regex18)); // 输出: ["aaaab"]​// 非贪婪模式案例​

const text19 = "aaaab";const regex19 = /a*?b/;​

console.log(text19.match(regex19)); // 输出: ["ab"]​// 提取HTML标签内内容的案例​

const text20 = "<div>content1</div><div>content2</div>";const greedyRegex = /<div>.*</div>/;const nonGreedyRegex = /<div>.*?</div>/g;​

console.log(text20.match(greedyRegex));// 输出: ["<div>content1</div><div>content2</div>"]​

console.log(text20.match(nonGreedyRegex));// 输出: ["<div>content1</div>", "<div>content2</div>"]​

通过这些案例,可以清晰地看到贪婪模式和非贪婪模式在匹配行为上的差异。​

三、正则表达式的高级技巧​

(一)前瞻与后顾​

前瞻(Lookahead)和后顾(Lookbehind)是正则表达式中的高级功能。它们允许我们在匹配时考虑后面的或前面的字符,但不将其包含在匹配结果中。例如,“(?=abc) def” 表示匹配 “def”,但前提是它后面跟着 “abc”。​

// 正向前瞻案例​

const text21 = "defabc defxyz";const regex21 = /(?=abc)def/;​

console.log(text21.match(regex21)); // 输出: ["def"]​// 正向后顾案例​

const text22 = "abcdef xyzdef";const regex22 = /(?<=abc)def/;​

console.log(text22.match(regex22)); // 输出: ["def"]​

在 JavaScript 中,正向后顾在某些环境(如 Chrome 浏览器)中支持有限,上述代码在支持正向后顾的环境中运行。​

(二)递归匹配​

递归匹配是一种强大的功能,可以用于匹配嵌套的结构,如括号嵌套。例如,“​

(?>[()]+∣(?R))∗

” 可以匹配嵌套的括号结构。​

const text23 = "((a + b) * (c - d))";const regex23 = /\((?>[^()]+|(?R))*\)/;​

console.log(text23.match(regex23));// 输出: ["((a + b) * (c - d))"]​const text24 = "((a + b) * (c - d)";​

console.log(text24.match(regex23));// 输出: null​

这个案例展示了递归匹配在处理嵌套结构时的有效性,以及在括号不完整时匹配失败的情况。​

(三)性能优化​

正则表达式的性能优化非常重要,尤其是在处理大量文本时。避免使用过于复杂的正则表达式,尽量减少回溯次数,可以提高匹配效率。​

// 低效的匹配单词方式​

const longText = "这是一篇很长很长的文档,包含了很多单词,比如apple, banana, cherry等等";const inefficientRegex = /[a-zA-Z]+|[^a-zA-Z]+/g;​

console.time("inefficientMatch");​

longText.match(inefficientRegex);​

console.timeEnd("inefficientMatch"); ​

​

// 高效的匹配单词方式(先分割)​

console.time("efficientMatch");const words = longText.split(/[^a-zA-Z]+/).filter(word => word.length > 0);​

console.timeEnd("efficientMatch"); ​

​

在这个案例中,通过console.time和console.timeEnd方法可以对比两种方式的执行时间,明显可以看出先分割的方式在处理大量文本时性能更优。​

四、正则表达式的实践案例​

(一)数据清洗​

在数据处理中,正则表达式可以用于清洗文本数据。例如,去除文本中的多余空格、特殊字符等。​

// 去除多余空格​

const text25 = " 你好,世界! ";const regex25 = /\s+/g;const cleanText25 = text25.replace(regex25, " ");​

console.log(cleanText25);// 输出: 你好,世界!​// 去除特殊字符​

const text26 = "!@#Hello, World$%^";const regex26 = /[!@#$%^&*(),.?":{}|<>]/g;const cleanText26 = text26.replace(regex26, "");​

console.log(cleanText26);// 输出: Hello, World​

通过这些案例,我们可以看到正则表达式在数据清洗方面的便捷性。​

(二)文本提取​

从网页或文档中提取特定信息,如标题、链接、日期等,正则表达式是一个非常有用的工具。​

// 从网页中提取链接​

const htmlText = "<a href=\"http://example1.com\">链接1</a><a href=\"http://example2.com\">链接2</a>";const linkRegex = /<a href="([^"]+)">/g;const links = htmlText.match(linkRegex);if (links) {​

links.forEach(link => {const url = link.match(/"([^"]+)"/)[1];​

console.log(url);// 输出: http://example1.com, http://example2.com​

});}​

​

// 从文档中提取标题​

const docText = "# 标题1\n内容1\n# 标题2\n内容2";const titleRegex = /^# (.*)$/gm;const titles = docText.match(titleRegex);if (titles) {​

titles.forEach(title => {const titleText = title.match(/# (.*)/)[1];​

console.log(titleText);// 输出: 标题1, 标题2​

});}​

​

这里的 “m” 标志表示多行匹配,使得正则表达式能够匹配每一行以 “# ” 开头的内容。​

(三)代码分析​

在代码编辑器中,正则表达式可以用于高亮显示特定的代码模式,如注释、关键字等。​

const code = "# 这是一个注释\nprint('Hello, World!')";const commentRegex = /#.*$/gm;const highlightedCode = code.replace(commentRegex, match => `<span style="color: green;">${match}</span>`);​

console.log(highlightedCode);// 输出: <span style="color: green;"># 这是一个注释</span>​

// print('Hello, World!')​const keywordRegex = /\b(print|def|class|if|else|for|while)\b/g;const keywordHighlightedCode = highlightedCode.replace(keywordRegex, match​
=> <span style="color: blue;">${match}</span>);​
console.log (keywordHighlightedCode);// 输出: # 这是一个注释​
// print('Hello, World!')​
// 匹配函数定义​
const code2 = "def add (a, b):\n    return a + b";const functionRegex = /def\s+(\w+)\s*

(.?)
:/gm;const functions = code2.match(functionRegex);if (functions) {​
functions.forEach(func => {const name = func.match(/def\s+(\w+)\s*

(.?)
:/)[1];​
console.log(函数名: ${name});// 输出:函数名: add​
});}// 匹配变量声明​
const code3 = "int num = 10;\nstring text = 'Hello';";const variableRegex = /\b\w+\s+\w+\s*=/g;const variables = code3.match (variableRegex);if (variables) {​
console.log (variables);// 输出: ["int num =", "string text ="]​
}​

​
http://www.dtcms.com/a/112408.html

相关文章:

  • 基于 LangChain 搭建简单 RAG 系统
  • Mysql 中的两阶段提交
  • HTML应用指南:利用POST请求获取三大运营商5G基站位置信息(一)
  • 2025-04-04 Unity 网络基础5——TCP分包与黏包
  • Windows 安装和使用 ElasticSearch
  • Git提交本地项目到Github
  • vue+form实现flappybird
  • 迅饶科技X2Modbus网关-GetUser信息泄露漏洞
  • Mysql 中 B 树 vs B+ 树
  • SQL Server 2022 脏读问题排查与思考
  • HTML5 vs HTML 和 CSS3 vs CSS:全面对比
  • Spring Boot 中使用 Redis:从入门到实战
  • Websoft9分享:在数字化转型中选择开源软件可能遇到的难题
  • 神经网络能不能完全拟合y=x² ???
  • WinForm真入门(7)——Button控件详解
  • 京东运维面试题及参考答案
  • k8s进阶之路:本地集群环境搭建
  • 谷歌 Gemini 2.5 Pro 免费开放
  • 24、 Python Socket编程:从协议解析到多线程实战
  • 如何完整迁移 Git 仓库 ?
  • yum list查询时部分包查找不到流程分析
  • 54.大学生心理健康管理系统(基于springboot项目)
  • 有人DTU使用MQTT协议控制Modbus协议的下位机-含数据库
  • Redis分布式锁详解
  • AWS Langfuse AI用Bedrock模型使用完全教程
  • 【万字总结】前端全方位性能优化指南(八)——Webpack 6调优、模块联邦升级、Tree Shaking突破
  • 安卓离线畅玩的多款棋类单机游戏推荐
  • 【leetcode100】动态规划Java版本
  • Debezium日常分享系列之:Debezium 3.1.0.Final发布
  • 什么是量子计算?