myDocs
首页
  • JavaScript小记
  • HTML小记
  • CSS小记
  • 计算机网络
  • React小记
  • Vue小记
  • 手写js
  • 前端工程化
  • 前端性能优化
  • 实际项目开发
  • Typescript面试题
  • Nodejs面试题
  • 小程序
  • 排序
  • 算法题
  • Git小记
  • NodeJs小记
  • TypeScript小记
  • 正则表达式入门
  • Linux基本命令
  • PixiJS的基本使用
  • PixiJS实现一镜到底
  • Canvas入门
  • SVG入门
  • Echarts基本使用
  • antv G6的基础入门及树图的实际应用
  • Three.js
  • 《CSS揭秘》
  • 《Python编程:从入门到实践》
  • 低代码数据可视化平台开发记录
  • 中后台管理系统模板记录
  • 多页签开发记录
  • 浙政钉、浙里办、浙江政务服务网应用上架指南
Github
首页
  • JavaScript小记
  • HTML小记
  • CSS小记
  • 计算机网络
  • React小记
  • Vue小记
  • 手写js
  • 前端工程化
  • 前端性能优化
  • 实际项目开发
  • Typescript面试题
  • Nodejs面试题
  • 小程序
  • 排序
  • 算法题
  • Git小记
  • NodeJs小记
  • TypeScript小记
  • 正则表达式入门
  • Linux基本命令
  • PixiJS的基本使用
  • PixiJS实现一镜到底
  • Canvas入门
  • SVG入门
  • Echarts基本使用
  • antv G6的基础入门及树图的实际应用
  • Three.js
  • 《CSS揭秘》
  • 《Python编程:从入门到实践》
  • 低代码数据可视化平台开发记录
  • 中后台管理系统模板记录
  • 多页签开发记录
  • 浙政钉、浙里办、浙江政务服务网应用上架指南
Github
  • 正则表达式入门

正则表达式入门

参考来源:JS正则表达式完整教程

介绍

正则表达式其实就是一门工具,是一种用来描述规则的表达式,目的是为了字符串模式匹配,从而实现搜索和替换功能。

正则表达式是匹配模式,要么匹配字符,要么匹配位置。

可以利用工具很好地可视化自己写的正则表达式:

可视化正则表达式

可视化正则

修饰语

修饰语作用
i忽略大小写
g全局搜索
m多行

相关操作api

api作用
String#search查找是否包含,返回找到的位置index
String#split按照某个正则表达式将字符串分隔开
String#match返回你所匹配到的内容
String#replace替换字符串中的匹配内容
RegExp#test测试是否包含,返回一个boolean变量
RegExp#exec实现匹配全局,并返回分组的结果

匹配字符

精确匹配

精确匹配字面量

字面量,匹配一个具体字符,包括不用转义的和需要转义的。比如a匹配字符"a",又比如\n匹配换行符,又比如.匹配小数点。

var regex = /hello/;
console.log(regex.test("hello")); 
// => true

模糊匹配

横向模糊匹配

  • 可匹配的字符串的长度不是固定的
  • 通过使用量词来实现

例 {m,n}:连续出现最少m次,最多n次。

var regex = /ab{2,5}c/g;
var string = "abc abbc abbbc abbbbc abbbbbc abbbbbbc";
console.log(string.match(regex)); 
// => ["abbc", "abbbc", "abbbbc", "abbbbbc"]

可视化:/ab{2,5}c/g

量词
字符描述
*匹配0~n位字符。如 /b*/g,就是可以不出现b,也可以出现一次或多次。
+匹配1~n位字符。如 /b+/g,就是至少出现一次b。
??之前字符可选,0或1位。如 /colou?r/g,就是可以匹配color或colour。
{n}匹配确定的 n 位。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}至少匹配 n 位。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}匹配n~m位字符。如 /b{n,m}/g,就是最少出现n次b,最多出现m次b。

纵向模糊匹配

  • 匹配字符串,具体到某一位字符时,可以有多种可能
  • 使用字符组[]来实现

例 [abc]:匹配abc中的一个

var regex = /1[abc]2/g;
var string = "1a2 1b2 1c2 1d2 1e2";
console.log( string.match(regex) ); 
// => ["1a2", "1b2", "1c2"]

可视化:/1[abc]2/g

字符组

1、排除字符组

字符组的第一位放^(脱字符),表示求反的概念。

例如[^abc],表示是一个除"a"、"b"、"c"之外的任意一个字符。

2、范围表示法

用连字符-来省略和简写。

比如[123456abcdefGHIJKLM],可以写成[1-6a-fG-M]。

3、常见简写

简写作用
\wword的简写。匹配字母、数字、下划线。
\W匹配非字母、数字、下划线。
\sspace的简写。匹配任意的空白符,包括空格、制表符、换行符、回车符、换页符。
\S匹配非空白符。
\ddigit的简写。匹配数字。
\D匹配非数字。
.匹配任意除了换行符(回车键)之外的单个字符。

**匹配任意字符:**可以使用[\d\D]、[\w\W]、[\s\S]和[^]中任何的一个。

贪婪匹配 和 惰性匹配

量词的匹配

{m,n}默认是贪婪匹配,它会尽可能多的匹配

var regex = /\d{2,5}/g;
var string = "123 1234 12345 123456";
console.log( string.match(regex) ); 
// => ["123", "1234", "12345", "12345"]

正则/\d{2,5}/,表示数字连续出现2到5次。会匹配2位、3位、4位、5位连续数字。

惰性匹配,就是尽可能少的匹配。通过在量词后面加个问号就能实现惰性匹配。

var regex = /\d{2,5}?/g;
var string = "123 1234 12345 123456";
console.log( string.match(regex) ); 
// => ["12", "12", "34", "12", "34", "12", "34", "56"]

其中/\d{2,5}?/表示,虽然2到5次都行,当2个就够的时候,就不在往下尝试了。

分支结构的匹配

多选分支

多选分支可以支持多个子模式任选其一。

具体形式如下:(p1|p2|p3),其中p1、p2和p3是子模式,用|(管道符)分隔,表示其中任何之一。

例如要匹配"good"和"nice"可以使用/good|nice/。测试如下:

var regex = /good|nice/g;
var string = "good idea, nice try.";
console.log( string.match(regex) ); 
// => ["good", "nice"]

分支结构属于惰性匹配。 如果前面的匹配上了,后面就不再尝试了

var regex = /good|goodbye/g;
var string = "goodbye goodnight";
console.log( string.match(regex) ); 
// => ["good", "good"]
var regex = /goodbye|good/g;
var string = "goodbye goodnight";
console.log( string.match(regex) ); 
// => ["goodbye", "good"]

示例

匹配16进制颜色值

var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
var string = "#ffbbad #Fc01DF #FFF #ffE";
console.log( string.match(regex) ); 
// => ["#ffbbad", "#Fc01DF", "#FFF", "#ffE"]

匹配位置

锚点

匹配一个位置,而不是字符。

锚点作用
^匹配开头,在多行匹配中匹配行开头。
$匹配结尾,在多行匹配中匹配行结尾。
\b匹配单词的开始和结束也包括\w和^之间的位置,也包括\w和$之间的位置。
\B非单词边界
(?=pattern)正向先行断言,匹配pattern前面的位置
(?!pattern)反向先行断言,匹配不是pattern前面的位置
(?<=pattern)正向后行断言,匹配pattern后面的位置
(?<!pattern)反向后行断言,匹配不是pattern后面的位置

开始 ^ 结束 $

例:将字符串的开头和结尾用"#"替换(位置也可以替换成字符)

var result = "hello".replace(/^|$/g, '#');
console.log(result); 
// => "#hello#"

多行匹配模式时,二者是行的概念,这个需要我们的注意:

var result = "How\nare\nyou".replace(/^|$/gm, '#');
console.log(result);
/*
#How#
#are#
#you#
*/

单词边界 \b \B

var result = "Hey!Good morning".replace(/\b/g, '#');
console.log(result); 
// => "#Hey#!#Good# #morning#"
var result = "Hey!Good morning".replace(/\B/g, '#');
console.log(result); 
// => "H#e#y!G#o#o#d m#o#r#n#i#n#g"

正向先行断言 (?=pattern)

匹配pattern前面的位置

var result = "goodbye".replace(/(?=good)/g, '#');
console.log(result); 
// => "#goodbye"

反向先行断言 (?!pattern)

匹配不是pattern前面的位置,与上述匹配相反的位置

var result = "goodbye".replace(/(?!good)/g, '#');
console.log(result); 
// => "g#o#o#d#b#y#e#"

正向后行断言 (?<=pattern)

匹配pattern后面的位置

var result = "goodbye".replace(/(?<=good)/g, '#');
console.log(result); 
// => "good#bye"

反向后行断言 (?<!pattern)

匹配不是pattern后面的位置,与上述匹配相反的位置

var result = "goodbye".replace(/(?<!good)/g, '#');
console.log(result); 
// => "#g#o#o#db#y#e#"

示例

不匹配任何东西的正则

/.^/ 匹配开头前面的任意字符

金额的千位分隔符表示法

var string = "12345678.12 123456789.12",
reg = /\B(?=(\d{3})+\b)/g;

var result = string.replace(reg, ',')
console.log(result); 
// => "12,345,678.12 123,456,789.12"

可视化:[/\B(?=(\d{3})+\b)/g](https://jex.im/regulex/#!flags=&re=%5CB(%3F%3D(%5Cd%7B3%7D)%2B%5Cb)

分组(括号的使用)

我们知道/a+/匹配连续出现的“a”,而要匹配连续出现的“ab”时,需要使用/(ab)+/。

其中括号是提供分组功能,使量词+作用于“ab”这个整体,测试如下:

var regex = /(ab)+/g;
var string = "ababa abbb ababab";
console.log( string.match(regex) ); 
// => ["abab", "ab", "ababab"]

引用分组

一个括号表示一个分组,通过$1、$2引用分组

比如,想把yyyy-mm-dd格式,替换成mm/dd/yyyy怎么做?

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2021-08-19";
var result = string.replace(regex, "$2/$3/$1");
console.log(result); 
// => "06/12/2017"

其中replace中的,第二个参数里用$1、$2、$3指代相应的分组。

反向引用

除了使用相应API来引用分组,也可以在正则本身里引用分组。但只能引用之前出现的分组,即反向引用。

通过\1、\2进行引用 \0则表示整个表达式

例:匹配成对标签

var regex = /<([^>]+)>[\d\D]*<\/\1>/;
var string1 = "<title>regular expression</title>";
var string2 = "<p>laoyao bye bye</p>";
var string3 = "<title>wrong!</p>";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // false

非捕获分组

(?:pattern) 非捕获分组匹配的值不会保存起来。 只保留括号最原始的功能,不会引用它。

即,既不在API里引用,也不在正则里反向引用。

var regex = /(?:ab)+/g;
var string = "ababa abbb ababab";
console.log(string.match(regex)); 
// => ["abab", "ab", "ababab"]

示例

将每个单词的首字母转换为大写

function titleize(str) {
	return str.toLowerCase().replace(/(?:^|\s)\w/g, function(c) {
		return c.toUpperCase();
	});
}
console.log(titleize('my name is ccc') ); 
// => "My Name Is Ccc"

其他

操作符优先级

操作符的优先级从上至下,由高到低:

1.转义符 \

2.括号和方括号 (...)、(?:...)、(?=...)、(?!...)、(?<=...)、(?<!...)、[...]

3.量词限定符 {m}、{m,n}、{m,}、?、*、+

4.位置和序列 ^ 、$、 \元字符、 一般字符

5.管道符(竖杠)|

示例

匹配 ipv4

/^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/

结构:((...)\.){3}(...)

它是一个多选结构,分成5个部分:

  • 0{0,2}\d,匹配一位数,包括0补齐的。比如,9、09、009;
  • 0?\d{2},匹配两位数,包括0补齐的,也包括一位数;
  • 1\d{2},匹配100到199;
  • 2[0-4]\d,匹配200-249;
  • 25[0-5],匹配250-255。

拓展阅读

《JavaScript权威指南》 第10章

《高性能JavaScript》 第5章

《JavaScript高级程序设计》 第5.4节

最近更新: 2024/8/30 03:22
Contributors: csmSimona