一文搞定正则表达式

391 阅读2分钟

正则表达式组成

正则表达式是由普通字符(例:字符a~z)以及特殊字符(元字符)组成的文字模式。正则表达式作为一个模版将某个字符模式与所有搜索的字符串进行匹配。

正则表达式 = 普通字符 + 特殊字符(元字符)

匹配符

字符匹配符用于匹配某个或某些字符

在正则表达式中,通过一组方括号括起来的内容,我们就称之为字符簇,其表示的是一个范围,但是实际匹配时,只能匹配固定的某个字符。

[a-z]:匹配小写字母从a-z中的任意字符

[A-Z]:匹配大写字母从A-Z中的任意字符

[0-9]:匹配数字从0-9中的任意字符,相当于\d

[0-9a-z]:匹配数字0-9或小写字母从a-z中的任意字符

[0-9a-zA-Z]:匹配数字0-9,小写字母从a-z或大写字母A-Z中的任意字符

[abcd]:匹配字符abcd中的任意字符

[1234]:匹配数字1234中的任意字符

在字符簇中存在一个特殊符号^(脱字节),脱字节在字符簇代表取反的含义

[^a-z]:匹配除了小写字母从a-z之外的任意字符

在正则表达式中还有一类特殊字符:

\d:匹配一个数字字符,用字符簇[0-9]表示

\D:匹配一个非数字字符,也可以使用字符簇[^0-9][^\d]来表示

\w:匹配包括下划线的任何单词字符,用字符簇[0-9a-zA-Z_]

\W:匹配任何非单词字符,[^0-9a-zA-Z_][^\w]

\s:匹配任何空白字符,空格、制表符、换行符都可以通过\s匹配

\S:匹配任何非空白字符,[^\s]

.(点):匹配除\n之外的任何单个字符

var str = 'abcdefgh';
// 定义一个正则表达式,匹配bch中的任意一个字符
var reg = '/[bch]/gi'
alert(str.match(reg));

修饰符

reg = /pattern/[switch] => /正则表达式主体/修饰符(可选)

switch(修饰符):

g:全局匹配

i:忽略大小写

m:多行模式multiline 只有当目标字符串含有\n,而且正则表达式中含有^或$的时候,/m修饰符才有作用

gi:全局匹配 + 忽略大小写

y:“粘连”

y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。

实际上,y修饰符号隐含了头部匹配的标志^

u:“Unicode 模式”,用来正确处理大于\uFFFF的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码。

一旦加上u修饰符号,就会修改下面这些正则表达式的行为。

  1. 点字符

点(.)字符在正则表达式中,含义是除了换行符以外的任意单个字符。对于码点大于0xFFFF的Unicode字符,点字符不能识别,必须加上u修饰符

let s = '𠮷';
/^.$/.test(s) // false
/^.$/u.test(s) // true

//上面代码表示,如果不添加u修饰符,正则表达式就会认为字符串为两个字符,从而匹配失败。
  1. Unicode 字符表示法

ES6 新增了使用大括号表示 Unicode 字符,这种表示法在正则表达式中必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词。

  1. 量词

使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的 Unicode 字符。

4.预定义模式

u修饰符也影响到预定义模式,能否正确识别码点大于0xFFFF的 Unicode 字符。

/^\S$/.test('𠮷') // false
/^\S$/u.test('𠮷') // true

//上面代码的\S是预定义模式,匹配所有非空白字符。只有加了u修饰符,它才能正确匹配码点大于0xFFFF的 Unicode 字符。
  1. i 修饰符

有些 Unicode 字符的编码不同,但是字型很相近,比如,\u004B\u212A都是大写的K

/[a-z]/i.test('\u212A') // false
/[a-z]/iu.test('\u212A') // true
// 上面代码中,不加u修饰符,就无法识别非规范的K字符。
  1. 转义

没有u修饰符的情况下,正则中没有定义的转义(如逗号的转义\,)无效,而在u模式会报错。

/\,/ // /\,/
/\,/u // 报错

//上面代码中,没有u修饰符时,逗号前面的反斜杠是无效的,加了u修饰符就报错。

unicode 属性

正则实例对象新增unicode属性,表示是否设置了u修饰符。

const r1 = /hello/;
const r2 = /hello/u;

r1.unicode // false
r2.unicode // true

//上面代码中,正则表达式是否设置了u修饰符,可以从unicode属性看出来。

限定符

限定符可以指定正则表达式的一个给定组件必须要出现多少次才满足匹配

*:匹配前面的子表达式零次或多次,0到多,可以使用{0,}代替

+:匹配前面的子表达式一次或多次,1到多,可以使用{1,}代替

?:匹配前面的子表达式零次或多、一次,0或1,可以使用{0,1}代替

{n}:匹配确定的n次,如{20},连续匹配20次

{n,}:至少匹配n次,如{20,},代表最少匹配20次

{n,m}:至少匹配n次且最多匹配m次,如{1,7}代表最少匹配1次且最多匹配7次

在正则表达式中,我们把匹配多的就不匹配少的情况,称之为“贪婪匹配原则”,正则表达式默认使用的就是贪婪匹配原则。

在正则表达式我们也可以在限定符的后面添加一个问号(?)来改变匹配原则为“非贪婪匹配原则”,能匹配少的就不匹配多的。

var strg = 'abc1233333defh'
// 至少匹配2个连续的数字,非贪婪匹配原则
var reg = /\d{2,3}?/gi
console.log(strg.match(reg)) // ["12", "33", "33"]

定位符

定位符可以将一个正则表达式固定在一行的开始或结束。也可以创建只在单词内或只在单词的开始或结束处出现的正则表达式。

^:匹配输入字符串的开始位置(以***开始)

$:匹配输入字符串的结束位置(以***结束)

\b:匹配另一个单词边界(字符串开头、结尾、空格、逗号、点号等符号)

\B:匹配非单词边界

\s:查找空白字符

\uxxxx:查找以十六进制数xxxx规定的Unicode字符

转义符

在正则表达式中,如果遇到特殊符号,我们必须要使用转义字符(反斜杠\)来进行转义。

[ ] * + ? .(点) / \ ^ $

选择匹配符

在正则表达式中,如果要匹配的内容包含多个选择,我们可以通过|选择匹配符来进行匹配

let str = 'hellocss,hellojavascript';
//匹配hellocss或hellojavascript
var reg = /hello(css|javascript)/gi;
console.log(str.match(reg)) //["hellocss", "hellojavascript"]

特殊用法

  1. (?=) :正向预查

匹配结果?=匹配条件,必须满足匹配条件,才会输出匹配结果

let str = '太阳温暖,太阳凉爽';
// 匹配后面是温暖的太阳
var reg = /太阳(?=温暖)/gi;
console.log(str.match(reg)) //["太阳"]
  1. (?!) :负向预查
let str = '太阳温暖,太阳凉爽';
// 匹配后面不是温暖的太阳
var reg = /太阳(?!温暖)/gi;
console.log(str.match(reg)) //["太阳"]
  1. (?:) :输出内容,但不捕获

字符串的正则方法

  1. test()

test() 方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。

  1. exec()

exec() 方法用于检索字符串中的正则表达式的匹配。该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

  1. split()

可以将一个字符串拆分为一个数组,方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串

var str="1a2B3d4g5c6"
var result=str.split(/[A-Z]/i)
console.log(result)//["1", "2", "3", "4", "5", "6"]
  1. search()
  • 可以搜索字符串中是否含有指定内容
  • 如果搜索到指定内容,则会返回第一次出现到索引,如果没有搜索到,则返回-1
  • 它可以接收一个正则表达式作为参数,然后根据正则表达式去检索字符串
  1. match()
  • 找到一个便停止查找,若要全部找出,可配合使用正则表达式
var str="sun his little Sun"; 
var n=str.match("sun");//sun

var str="sun is little Sun"; 
var n=str.match(/sun/gi);//全局查找,忽略大小写
//sun,Sun
  1. replace()
  • string.replace(searchvalue,newvalue)

在字符串中查找并替换“morning”:

var str="Good morning! Good morning!";
var n=str.replace("morning","evening");
//"Good evening! Good morning!"


var str="Good morning! Good morning!";
var n=str.replace(/morning/gi,"evening");//全局替换,忽略大小写
//"Good evening! Good evening!"

sticky 属性

y修饰符相匹配,ES6 的正则实例对象多了sticky属性,表示是否设置了y修饰符。

var r = /hello\d/y;
r.sticky // true

flags 属性

ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符。

// ES5 的 source 属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"

// ES6 的 flags 属性
// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'

s 修饰符:dotAll 模式

ES2018 引入s修饰符,使得.可以匹配任意单个字符。

/foo.bar/s.test('foo\nbar') // true

这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。

const re = /foo.bar/s;
// 另一种写法
// const re = new RegExp('foo.bar', 's');

re.test('foo\nbar') // true
re.dotAll // true
re.flags // 's'

/s修饰符和多行修饰符/m不冲突,两者一起使用的情况下,.匹配所有字符,而^$匹配每一行的行首和行尾。