正则表达式总结

简介: 创建正则表达式1.使用RegExp()构造函数来创建RegExp()构造函数非常有用,特别是在需要动态创建正则表达式的时候,这种情况往往没办法通过写死在代码中的正则表达式直接量来实现。

创建正则表达式

1.使用RegExp()构造函数来创建

RegExp()构造函数非常有用,特别是在需要动态创建正则表达式的时候,这种情况往往没办法通过写死在代码中的正则表达式直接量来实现。
例如,如果待检索的字符串是由用户输入的,就必须使用RegExp()构造函数,在程序运行时创建正则表达式

var pattern = new RegExp("s$");
2.使用直接量语法来创建
var pattern = /s$/;

RegExp对象的属性

每个RegExp对象(即正则表达式对象)都有5个属性。

属性 属性描述
source 只读的字符串,包含正则表达式的文本
global 只读的布尔值,用以说明这个正则表达式是否带有修饰符g
ignoreCase 只读的布尔值,用以说明正则表达式是否带有修饰符i
multiline 只读的布尔值,用以说明正则表达式是否带有修饰符m
lastIndex 可读/写的整数,如果匹配模式带有g修饰符,这个属性存储在整个字符串中下一次检索的开始位置,这个属性会被exec()和test()方法用到,下面会讲到

直接量字符

字符 匹配
a-zA-Z0-9 匹配自身
\o NUL字符(\u0000)
\t 制表符(\u0009)
\n 换行符(\u000A)
\v 垂直制表符(\u000B)
\f 换页符(\u000C)
\r 回车符(\u000D)
\xnn 由十六进制数nn制定的拉丁字符,例如,\x0A等价于\n
\uxxxx 由十六进制数xxxx制定的Unicode字符,例如\u0009等价于\t
\cX 控制字符^X,例如,\cJ等价于换行符\n

字符类

将直接量字符单独放进方括号内就组成了字符类。一个字符类可以匹配它所包含的任意字符

字符 匹配
[...] 方括号内的任意字符
[^...] 不在方括号内的任意字符
. 除换行符和其他Unicode行终止符之外的任意字符
\w 任何ASCII字符组成的单词,等价于[a-zA-Z0-9]
\W 任何不是ASCII字符组成的单词,等价于[^a-zA-Z0-9]
\s 任何Unicode空白符
\S 任何不是Unicode空白符的字符,注意\S和\w不同
\d 任何ASCII数字,等价于[0-9]
\D 除了ASCII数字之外的任何字符,等价于[^0-9]
[\b] 退格直接量(特例)

重复

字符 含义
{n,m} 匹配前一项至少n次,但不能超过m次
{n,} 匹配前一项n次或更多次
{n} 匹配前一项n次
? 匹配前一项0次或者1次,也就是说前一项是可选的。等价于{0,1}
+ 匹配前一项一次货多次,等价于{1,}
* 匹配前一项0次或多次,等价于{0,}

非贪婪重复

  • 上表中列出的匹配重复字符是尽可能多地匹配,而且允许后续的正则表达式继续匹配。因此,我们称之为“贪婪的”匹配。

  • 我们同样可以使用正则表达式进行非贪婪匹配。只须在待匹配的字符后跟随一个问号即可:"??"、"+?"、"*?"或"{1,5}?"。

  • 比如,正则表达式 /a+/ 可以匹配一个或多个连续的字母a。当使用 "aaa" 作为匹配字符串时,正则表达式会匹配它的三个字符。但是 /a+?/ 也可以匹配一个或多个连续字母a,但它是尽可能少地匹配。我们同样将 "aaa" 作为匹配字符串,但后一个模式只能匹配第一个a。

  • 使用非贪婪的匹配模式所得到的结果可能和期望并不一致。考虑以下正则表达式 /a+b/ ,它可以匹配一个或多个a,以及一个b。当使用 "aaab" 作为匹配字符串时,它会匹配整个字符串。现在再试一下非贪婪匹配的版本 /a+?b/ ,它匹配尽可能少的a和一个b。当用它来匹配 "aaab" 时,你期望它能匹配一个a和最后一个b。但实际上,这个模式却匹配了整个字符串,和该模式的贪婪匹配一模一样。

  • 这是因为正则表达式的模式匹配总是会寻找字符串中第一个可能匹配的位置。由于该匹配是从字符串的第一个字符开始的,因此在这里不考虑它的子串中更短的匹配。

指定匹配位置

使用正则表达式的锚字符可以指定匹配的位置,可以指定正则表达式的匹配位置实在字符串的开头、结尾还是单词的边界处等。

字符 含义
^ 匹配正则表达式的开头,在多行检索中,匹配一行的开头
$ 匹配正则表达式的结尾,在多行检索中,匹配一行的结尾
\b 匹配一个单词的边界,简言之,就是位于字符\w和\W之间的位置,或位于字符\w和字符串的开头或者结尾的位置(但是需要注意,[\b]匹配的是退格符)
\B 匹配非单词边界的位置
(?=p) 零宽正向先行断言,要求接下来的字符都与p匹配,但不能包含匹配p的那些字符
(?!p) 零宽负向先行断言,要求接下来的字符都不与p匹配

修饰符

正则表达式的修饰符,用以说明高级匹配模式的规则。修饰符的位置是放在“/”符号之外的,也就是第二条斜线之后;或者是正则表达式的构造函数的第二个参数位置,

// 正则表达式构造函数的第二个参数,用来指定修饰符
var pattern = new RegExp("s$","igm");

// 直接量语法中,第二条斜线之后,指定修饰符
var pattern = /s$/igm;
字符 含义
i 执行不区分大小写的匹配
g 执行一个全局匹配,简言之,及找到所有的匹配,而不是找到第一个匹配之后即停止
m 多行匹配模式,^匹配每一行的开头和字符串的开头,$匹配每一行的结束和字符串的结束

选择

使用选择符 |,可以指定匹配的是该符号左边的子表达式还是右边的子表达式。例如:/ab|cd|ef/ 可以匹配字符串"ab",也可以匹配字符串"cd",还可以匹配字符串"ef"

字符 含义
| 匹配的是该符号左边的子表达式还是右边的子表达式

分组

分组是把单独的项组合成子表达式,以便可以像处理一个独立的单元那样用 |、*、+ 或者?等来对单元内的项进行处理。
不仅如此,分组后的子表达式还可以用于后期的引用,能够更大限度满足我们的需求。

字符 含义
(...) 组合,将几个项组合为一个单元,这个单元可以通过|、*、+** 或者?等符号加以修饰,而且可以记住和组合相匹配的字符串以供此后的引用使用
(?:) 只组合,把项组合到一个单元,但是不记忆和改组相匹配的字符

引用

对正则表达式中前一个子表达式的引用,并不是指对子表达式模式的引用,而指的是与那个模式相匹配的文本的引用。
正则表达式中有多个带圆括号的子表达式,可以使用\n的形式进行引用。
例如:\1引用的是第一个带圆括号的子表达式,\3引用的是第三个带
圆括号的子表达式。注意,因为子表达式可以嵌套另一个子表达式,所以它的位置是参与计数的左括号的位置。

字符 含义
\n 和第n个分组第一次匹配的字符相匹配,组是圆括号中的子表达式(也有可能是嵌套的),组索引是从左到右的左括号书。但是注意:"(?:)"形式的分组不编码,即不能引用

用于模式匹配的String方法

1.String.search(n)
  • 参数:正则表达式
  • 返回值:返回第一个与之匹配的子串的起始位置,如果找不到匹配的子串,它将返回-1。
  • 示例代码:
"JavaScript".search(/script/i);        // 返回值为4
  • 备注:如果search()的参数不是正则表达式,则首先会通过RegExp构造函数将它转换成正则表达式。search()方法不支持全局检索,因为它忽略正则表达式参数中的修饰符g。
2.String.replace(n1,n2)
  • 参数:第一个参数是一个正则表达式,第二个参数是要进行替换的字符串
  • 作用:
    • 这个方法会对调用它的字符串进行检索,使用指定的模式来匹配。
    • 如果正则表达式中设置了修饰符g,那么源字符串中所有与模式匹配的子串都将替换成第二个参数指定的字符串。
    • 如果不带修饰符g,则只替换所匹配的第一个子串。
  • 示例代码:
var text="Hello javascript ! javascript is very good !";
// 将所有不区分大小写的javascript都替换成大小写正确的JavaScript
var text2=text.replace(/javascript/gi,"JavaScript");
// 最终的text2是 "Hello JavaScript ! JavaScript is very good !"
console.log(text2);
  • 备注:。如果replace()的第一个参数是字符串而不是正则表达式,则replace()将直接搜索这个字符串,而不是像search()一样首先通过RegExp()将它转换为正则表达式。
3.String.match(n)
  • 参数:正则表达式
  • 返回值:
    • 返回的是一个由匹配结果组成的数组。如果该正则表达式设置了修饰符g,则该方法返回的数组包含字符串中的所有匹配结果。
    • 如果这个正则表达式没有设置修饰符g,match()就不会进行全局检索,它只检索第一个匹配。但即使match()执行的不是全局检索,它也返回一个数组。在这种情况下,数组的第一个元素就是匹配的字符串,余下的元素则是正则表达式中用圆括号括起来的子表达式。
    • 因此,如果match()返回一个数组a,那么a[0]存放的是完整的匹配,a[1]存放的则是与第一个用圆括号括起来的表达式相匹配的子串,以此类推。
  • 示例代码:
var url=/(\w+):\/\/([\w.]+)\/(\S*)/;
var text="Visit my blog at http://www.example.com/~david";
var result=text.match(url);
if(result!=null){
    var fullurl=result[0];      //包含"http://www.example.com/~david"
    var protocol=result[1];     //包含"http"
    var host=result[2];         //包含"www.example.com"
    var path=result[3];         //包含"~david"
}
4.String.split(n)
  • 参数:正则表达式
  • 作用:将传入的参数作为边界条件,将调用它的字符串拆分为一个子串组成的数组
  • 返回值:返回拆分后的字符串组成的数组
  • 示例代码:
"123,456,789".split(",");//返回["123","456","789"]

"1,2,3,4,5".split(/\s*,\s*/);//返回["1","2","3","4","5"]

用于模式匹配的RegExp方法

1.RegExp.exec(n)
  • 参数:字符串
  • 作用:exec()方法对一个指定的字符串执行一个正则表达式,简言之,就是在一个字符串中执行匹配检索。
  • 返回值:
    • 如果它没有找到任何匹配,它就返回null;
    • 如果它找到了一个匹配,它将返回一个数组,就像match()方法为非全局检索返回的数组一样。
    • 这个数组的第一个元素包含的是与正则表达式相匹配的字符串,余下的元素是与圆括号内的子表达式相匹配的子串。
    • 和match()方法不同,不管正则表达式是否具有全局修饰符g,exec()都会返回一样的数组。
    • 回忆一下,当match()的参数是一个全局正则表达式时,它返回由匹配结果组成的数组。相比之下,exec()总是返回 当前匹配的一个匹配结果 ,并提供关于本次匹配的完整信息。
    • 当调用exec()的正则表达式对象具有修饰符g时,它将把当前正则表达式对象的lastIndex属性设置为紧挨着匹配子串的字符位置。
    • 当同一个正则表达式第二次调用exec()时,它将从lastIndex属性所指示的字符处开始检索。如果exec()没有发现任何匹配结果,它会将lastIndex重置为0(在任何时候都可以将lastIndex属性设置为0,每当在字符串中找最后一个匹配项后,在使用这个RegExp对象开始新的字符串查找之前,都应当将lastIndex设置为0)。
    • 这种特殊的行为使我们可以在用正则表达式匹配字符串的过程中反复调用exec(),
  • 示例代码:
var pattern=/java/img;
var text="I love JAVA and JavaScript. I think javascript is more interesting";
// 第一次调用,返回的信息:["JAVA", index: 7, input: "text的文本内容", groups: undefined]
console.log(pattern.exec(text));
// 第二次调用,返回的信息:["Java", index: 16, input: "text的文本内容", groups: undefined]
console.log(pattern.exec(text));
// 第三次调用,返回的信息:["java", index: 36, input: "text的文本内容", groups: undefined]
console.log(pattern.exec(text));
  • 备注:exec()方式是RegExp对象的主要方法,大家仔细阅读上面的介绍,一定能明白这个方法。
2.RegExp.test(n)
  • 参数:字符串
  • 返回值:用test()对某个字符串进行检测,如果包含正则表达式的一个匹配结果,则返回true,否则返回false。
  • 示例代码:
var pattern=/java/i;
pattern.test("JavaScript");         // 返回true
pattern.test("feng");               // 返回false
相关文章
|
2月前
|
存储 缓存 人工智能
Agent运行机制拆解:上下文、检查点、任务恢复以及循环执行、资源管控完整流程23.3
本文系统解析大模型Agent的核心运行机制,涵盖执行循环、上下文与状态管理、工具反馈、检查点、停止条件、资源管控及人工接管等十大模块,揭示其“自主迭代、容错可溯、可控可兜底”的本质,助力开发者构建稳定智能体应用。
277 2
|
3月前
|
存储 JavaScript 安全
dsh 拆解系列 Vol.01:没有特权内核的 Agent 运行时
DeepSeek Harness(dsh)是DeepSeek开源的Agent运行时框架,秉持“一切皆插件”理念,将模型适配器、工具、会话、主循环等全部解耦为可配置、可替换、可卸载的插件,基于Cordis元框架实现时空可组合性。当前v0.1.0-rc.7为开发者预览版,MIT协议,强调工程可扩展性而非仅功能堆砌。
523 2
dsh 拆解系列 Vol.01:没有特权内核的 Agent 运行时
|
3月前
|
缓存 测试技术 API
大模型API中转站避坑:满血验证、倍率换算与降智识别(附压测代码)
从工程师视角系统梳理大模型API中转站的评估方法:讲清兑换比例与倍率的真实换算关系,给出满血模型验证三招(复杂推理压测、模型指认、长上下文压力测试)与可运行的Python压测脚本,并总结稳定性、协议兼容、计费透明等接入要点和先测后充的避坑建议。
|
4月前
|
运维 安全 Java
为什么不建议从零开发商城?集体放弃自研,转向开源二开的核心原因
电商技术选型核心在于规避隐性成本:自研商城看似自由,实则长期维护、迭代、安全投入巨大;成熟开源系统可省60%无效开发。本文对比VortMall(高并发多业态)、TigShop(全开源Java/低二开成本)、Jinor(PHP轻量快启)等5大主流方案,聚焦架构弹性、源码透明、生态持续与场景匹配,助企业精准降本增效。
399 0
为什么不建议从零开发商城?集体放弃自研,转向开源二开的核心原因
|
4月前
|
运维 监控 小程序
共享物联网设备平台搭建全科普:技术栈选型、云服务器运维与交易支付、合规分账全链路落地
共享充电桩、共享按摩椅、自助售货机、共享棋牌室、共享洗车机等物联网无人设备持续普及。一套商业化共享设备平台,不只是硬件联网与小程序页面开发,还包含完整技术栈规划、云端服务器部署、常态化运维、扫码交易支付体系,以及联营模式下多方收益结算链路。 本文从工程实践角度,系统梳理共享设备平台主流技术栈选型方案、云服务器部署架构与运维要点,完整拆解扫码支付业务流程;重点剖析联营模式下两大行业共性痛点:支付原生接口 30% 分账比例限制、平台归集资金带来的 “二清” 合规隐患,对比不同资金清算建设路径,为共享设备创业者、后端架构师提供可落地的架构参考。
465 0
|
5月前
|
机器学习/深度学习 人工智能 算法
图解强化学习 |手算近端策略优化算法(PPO)
PPO(近端策略优化)是当前最主流的强化学习算法,以训练稳定、上手简单、泛化性强著称。它通过Actor-Critic双网络架构,结合PPO-Clip损失函数限制策略更新幅度,并利用GAE优势估计提升样本效率,广泛应用于游戏AI、机器人控制、大模型对齐等领域。
1357 3
|
6月前
|
人工智能 JSON 运维
2026 生产级 AI Agent 自动化:零重型框架,彻底解决多步任务不稳定难题
本文提出“文件即状态”轻量架构,用5个文件实现AI Agent多步任务的稳定执行,无需LangGraph等重型框架。支持断点续跑、幂等重试、跨Agent协同,个人开发者7天即可落地生产级自动化。(239字)
|
5月前
|
消息中间件 存储 监控
Java在JavaAgent与字节码增强技术中的应用(APM基石)
JavaAgent是一种特殊的JAR包,可以在JVM启动时(-javaagent)或运行时(AttachAPI)修改字节码。它利用Instrumentation接口,通过ClassFileTransformer在类加载前或重定义时替换字节码。
429 0
|
5月前
|
缓存 Rust Linux
Python 统一大业:uv 如何整合 Pip、Pyenv 和 Venv?
Python包管理长期饱受速度慢、依赖冲突之苦。Rust编写的`uv`横空出世——集Python版本管理、虚拟环境创建、依赖安装与锁定于一体,速度比pip快10–100倍,真正实现“All-in-One”极速开发体验。(239字)
738 0
|
9月前
|
消息中间件 缓存 NoSQL
开源跑腿系统源码整体架构解析,从下单到配送的完整流程设计
本文深度解析同城跑腿平台的核心技术架构,聚焦高并发下单、实时智能调度、稳定资金结算与多城市扩展四大关键能力。强调订单与调度解耦、Redis GEO定位、消息队列异步削峰等实战设计,揭示开源源码在自主可控、降本增效与长期演进上的不可替代价值。(239字)