正则表达式

181 阅读6分钟

笔记来源:拉勾教育 - 大前端就业集训营

文章内容:学习过程中的笔记、感悟、和经验

正则表达式(Regular Expression)

用来匹配规律和规则的表达式,在js中通常用检索、替换符合某个规则的文本

对字符串操作的逻辑公式,使用预先设置好的特定字符及其组合组成一个规则字符串,表达对另一个字符串的一些过滤逻辑

正则表达式功能

  1. 匹配:检索字符串中是否符合正则表达式的过滤逻辑
  2. 提取:从字符串中符合正则表达式逻辑的字符
  3. 替换:可以根据正则表达式替换字符

正则表达式测试网站: c.runoob.com/front-end/8… ,提供常用的正则表达式

语法

创建正则表达式

在js中,正则表达式也是对象,是一种索引类型

  • 字面量创建:/正则规则/,左右两个/为正则表达式的定界符
  • 构造函数创建:var 变量名 = new RegExp("正则")
//正则表达式
//字面量创建
var zz1 = /abc/;

//构造函数方法创建
var zz2 = new RegExp('abc');

正则相关方法

字符串方法

方法说明
split()根据匹配字符切割字符串
match()返回匹配成功的结果的数组,字符串从头到尾匹配一遍
search()对正则表达式和字符串检索,返回第一个匹配项的下标
replace()用新的字符串替换匹配到的字符串

表达式方法

方法说明
exec()在目标字符串中执行一次匹配
test()测试字符串和正则能否匹配

split分割字符串

// 需求:字符串分隔后结果为["aa", "b", "ccc", "dddddd", "e"]
//创建一个字符串
var str = 'aa b   ccc dddddd e';

// 直接使用split分割字符串
var arr = str.split(' ');
console.log(arr); //发现出现了很多不应该出现的空字符串

// 使用正则表达式辅助split进行分割
// /\s+/正则表达式,\s代表空格转译,+代表可出现多次
var arr2 = str.split(/\s+/);
console.log(arr2); //发现是我们要的结果



// 练习:根据字母a切割字符,要求不管多少个a都算一个
//创建字符串
var str2 = 'yyajjjaaakannaaakalaiau';
var arr3 = str2.split(/a+/);
console.log(arr3);

// 解释:/a+/为正则表达式,其中/为定界符,a为需要匹配的字符,+代表可以出现多次
//总体意思就是匹配a字符,不管字符连续出现多少个

seach检索字符串方法

// 需求:搜索‘cd’出现的位置
//创建一个字符串
var str = 'abcdzzzzzefg';
//使用正则匹配字符串检索
var num = str.search(/z+/);
console.log(num);

match匹配字符串

// 需求:搜索全部b或者重复的b字符串
//创建一个字符串
var str = 'ssbeeebbbrrtwerrgdbbeefebb';
//方案1:直接使用正则匹配,但这种只会匹配一次之后就停下来
var arr = str.match(/b+/);
//方案2:使用边界符号g,g代表全局匹配,代表从头到尾都要匹配一遍,不管是否匹配成功过
var arr2 = str.match(/b+/g);
console.log(arr, arr2);


//练习:寻找一段字符串中‘o不管多少个空格o’的字符串
//创建字符串 
var str2 = 'sabdkusbuo   oasbdusbdsao osbadjasjbo            o';
//根据正则匹配
//正则/o\s+o/g中\s+代表两个o中间可以有多个空格存在
var arr3 = str2.match(/o\s+o/g);
console.log(arr3);

replace替换字符串方法

// 需求:修改替换文本
//创建一个字符串
var str = 'www.hello.com';
// 使用正则修改字符串,把hello改成byebye,这里直接精确匹配,后面在学习如何模糊匹配
var str2 = str.replace(/hello/, 'byebye');
console.log(str2);

exec尝试匹配方法

exec方法只会匹配一次,一旦成功一次,就会停止接下来的匹配,不管有没有全局修饰符g

test检查是否匹配方法

//创建一个字符串
var str = 'aaajiuyabcniknabc';

// 创建一个正则
var reg = /abc/;

//使用ecex匹配正则
var str2 = reg.exec(str);
console.log(str2);

//使用text匹配正则,返回布尔值
var what = /abcde/.test(str);
console.log(what);

正则表达式的组成

由一些普通字符和一些特殊字符(元字符)组成,普通字符包括大小写的字母和数字,元字符则具有特殊含义

特殊字符:()、[]、{}、\、^、$、|、?、*、+、.

特殊字符需要在前面使用转译符号\转译之后计算机才能识别,否则会被当作特殊字符来翻译

预定义特殊字符(不能直接写在正则里面吧):

  • \t:制表符(不常用)
  • \n:回车符
  • \f:换页符
  • \b或者\s:空格

普通字符会进行精确匹配,特殊字符会进行特殊模糊匹配

字符集

使用[]表示可能的字符的集合,集合内部列举了多种可能性,匹配的时候只要匹配到其中一个表示匹配成功,类似js的|的含义

  • 简单类型字符集
    • 字符集内部是一些简单字符,正则会匹配这些简单字符,例如/[abc]/
  • 范围类字符集
    • 字符集内部不是精确的简单字符,使用-连接两个简单字符确定范围,例如/[0-9]/、/[a-z]/
  • 负向类字符集(取反)
    • 字符集内部前面添加^符号,表示匹配不能为字符集里面的字符,例如/[^0-9]/
  • 组合类字符集
    • 如果我们有多个匹配需求,可以把上面的一些类组合在一起,例如/[0-9a-z]/

注意:范围组合类特殊方式可以简写,例如0-B表示0-9加A-B,因为这符合js编码顺序0-9A-Za-z,只要书写的顺序在这其中就可以简写

// 正则表达式字符集

// 简单类字符集
var reg = /[abc]/; // 表示匹配a或者b或者c,只要存在三者之一即成功
console.log(reg.test('ibuajbun'));
console.log(reg.test('noihtyuj'));
// 范围类字符集
var reg2 = /[0-9]/ // 表示匹配0-9的所有数字
console.log(reg2.test('hub3'));
console.log(reg2.test('hub'));
// 负向字符集
var reg3 = /[^0-9]/; // 表示匹配不是0-9之外的字符
console.log(reg3.test('8765578665'));
console.log(reg3.test('7867988h7889878'));
// 组合类字符集
// var reg4 = /[0-9A-U]/; // 表示匹配0-9和A-U之间的字符
var reg4 = /[0-U]/; // 这是上面的简写
console.log(reg4.test('sdfsdubdusv'));
console.log(reg4.test('asbdiasubdiEv'));


// 注:组合类只要是按照0-9A-Za-z排序的,就可以缩写,例如
// 0-8表示0-8
// 0-G表示0-9和A-G
// 0-b表示0-9和A-Z和a-b

修饰符

写在正则表达式字面量后面,拥有一些特殊效果

  • 全局修饰符g
    • 查找整个字符串,如果没有正则会在匹配到第一个之后结束
  • 大小写不敏感修饰符i
    • 模糊大小写界限,匹配即会匹配大写也会匹配小写
// 正则表达式修饰符

//全局修饰符g:全局匹配,会把整个字符串全部遍历,匹配出所有符合要求的字符
var reg = /a+/;
var reg2 = /a+/g;
var str1 = 'AbuasuabaubdauuaaasuabdubdsubsudAA';
console.log(str1.match(reg));
console.log(str1.match(reg2));
// 可以看到,reg只能匹配到一个,但是reg2却可以将全部a匹配出来


// 大小写不敏感修饰符i:忽略大小写差异
var reg3 = /a+/i;
console.log(str1.match(reg3));
// 可以发现,匹配到了大写的A,表示不管大小写,加上i都可以匹配到

// 组合使用
var reg4 = /a+/ig;
console.log(str1.match(reg4));
//可以发现,组合使用后,既可以全局匹配到所有a,又可以不分大小写全部匹配

边界符号

限定匹配字符串的开始和结束位置的字符

  • 开始符号^
    • 紧跟在正则表达式第一个字面量符号之后,/^匹配字符/
  • 结束符号$
    • 紧贴在最后一个字面量之前,/匹配字符$/

一般情况下,我们会组合使用,以限制某段文字的开头和结尾,例如判断用户输入的内容是否符合要求

// 正则表达式修饰符
// 字符串
var str = 'hello shuaige';

//开始边界符匹配
console.log(/^hello/.test(str));
console.log(/^you/.test(str));

//结束边界符匹配
console.log(/shuaige$/.test(str));
console.log(/shuaigenihao$/.test(str));


// 组合使用
console.log(/^hello\sshuaige$/.test(str));

预定义类

将一些常用的正则表达式使用特殊字符表示出来

预定义类说明等价于
.除换行和回车之外的任何字符[^\n\r]
\d数字字符[0-9]
\D非数字字符[^0-9]
\s空白字符,回车、空格都可以[\t\n\x0B\f\r]
\S非空白字符[^\t\n\x0B\f\r]
\w单词字符,字母、数字、下划线[0-9a-zA-Z_]
\W非单词字符[^0-9a-zA-Z_]
// 预定义类

// . 除回车换行以外的任何字符,只要不是回车换行就能匹配成功
// /^.+$/表示从头到尾都不会出现换行
console.log(/^.+$/.test('sdjbjksdjbfk')); //true
console.log(/^.+$/.test(`sdjbjks
djbfk`)); //flase

// 数字字符 \d 和 \D
// /^\d+$/表示从头到尾都要是数字
console.log(/^\d+$/.test('21345678')); //true
console.log(/^\d+$/.test('213dfs45678')); //flase

// 空白字符 \s 和 \S 
// /^\s+$/表示从头到尾都是空字符
console.log(/^\s+$/.test(`     
`)); //true
console.log(/^\s+$/.test(`     
sdfdfv`)); //flase

// 单词字符 \w 和 \W
// /^\w+$/表示从头到尾只能是单词字符,符号什么都不可以存在
console.log(/^\w+$/.test('sbddisdb67906455')); //true
console.log(/^\w+$/.test('sbddisdb67906455*^^')); //flase


//这里只写了成对的单个案例,相反案例可自行尝试

量词

规定正则表达式要求字符重复出现的次数

量词说明
{n}硬性量词,必须需连续出现n次
{n,m}软性量词,需要连续至少出现n次但不大于m次
{n,}软性量词,至少连续出现n次
{?}软性量词,出现0次或者1次,等价于{0,1}
{*}软性量词,出现0次或者多次,任意次,等价于{0,}
{+}软性量词,至少出现一次,等价于{1,}
// 量词

// 硬性量词
// /^\d{10}$/表示从头到尾只能是10个数字
console.log(/^\d{10}$/.test('1234567890'));

// 软性量词
// /^\d{5,10}$/表示从头带尾要是5-10个数字
console.log(/^\d{5,10}$/.test('12345'));
console.log(/^\d{5,10}$/.test('123456'));
console.log(/^\d{5,10}$/.test('1234567'));
console.log(/^\d{5,10}$/.test('12345678'));
console.log(/^\d{5,10}$/.test('1234567890'));
console.log(/^\d{5,10}$/.test('12345678900000'));

// /^\d{5,10}$/表示从头到尾要是5个数字
console.log(/^\d{5,}$/.test('1234'));
console.log(/^\d{5,}$/.test('12345'));
console.log(/^\d{5,}$/.test('123456'));
console.log(/^\d{5,}$/.test('1234567'));

//另外的预定义量词可以自行尝试

分组和或操作符

  • 分组():把重复的字符分成组,使用小括号括起来,
  • 或运算符|:判断运算符前后是否成立不成立,有一侧成立即成立
// 分组
// /(abc){3}/表示从头到尾必须是三个重复出现的abc,不可以拆开
console.log(/(abc){3}/.test('abcabcabc')); //true
console.log(/(abc){3}/.test('aaabbbccc')); //flase

// 或运算符:可以把前后分成两个部分分别判断,成立一个条件即可匹配成功
// /^ab|cd$/表示只能以ab开头或者以cd结尾的字符
console.log(/^ab|cd$/.test('abhsdkfbnjsife')); //true
console.log(/^ab|cd$/.test('abhsdkfbnjsifeccd')); //true 同时成立也没问题

//分组搭配或运算符
// /^(ab|cd)$/表示从头到尾只能是ab开头或者cd结尾并且还没有其他内容
console.log(/^(ab|cd)$/.test('abcd')); //flase
console.log(/^(ab|cd)$/.test('ab')); //true
console.log(/^(ab|cd)$/.test('cd')); //true

分组的反向引用

正则分组匹配出来的字符串可以再次引用,在正则内部可以使用\1引用,在正则表示是外面可以使用$引用

如果正则表达式哪出现多个分组,分组会按照从前到后的匹配结果编号

// 分组反向引用

// 正则表达式内引用
// /^([a-z]{3})\1$/,使用\1引用([a-z]{3})匹配到的结果组成匹配
console.log(/^([a-z]{3})\1$/.test('abcabc'));

// 正则表达式外引用
// /^(\w{3})\*(\w{3})/产生了两个分组匹配结果分别是123和7bu,而后面使用$1引用了123,使用$2引用了7bu。
var str = '123*7bu'.replace(/^(\w{3})\*(\w{3})/, '$2*$1');
// replace的第二个参数可以是一个函数,函数返回的结果可以当作replace的参数
var str2 = '123*7bu'.replace(/^(\w{3})\*(\w{3})/, function (match, $1, $2) {
  return $1 * 3 + '/' + $2;
});
console.log(str, str2);

匹配中文字符

[\u4e00-\u9fa5]`可代表中文字符范围