js 正则表达式

js 正则表达式

贪婪模式和非贪婪模式 
	所有语言中正则都是默认为贪婪模式的
	通过后追加 ? 将贪婪模式转化为非贪婪模式
	如
	// 贪婪模式
	const str = 'aaaaa';
	const reg = /\w?/g;
	console.log(str.match(reg)); // ['a', 'a', 'a', 'a', 'a', '']
	// 非贪婪模式
	const str = 'aaaaa';
	const reg = /\w??/g;
	console.log(str.match(reg)); // [ '', '', '', '', '', '' ]
	因为非贪婪模式 能匹配少 就不多匹配 ,?是匹配0次或1次。
匹配方式:
	1、字符串从左到右,依次先匹配多,在匹配少,如果一旦匹配上了就不回头匹配。
	2、贪婪匹配规则:能匹配上多个就不匹配少个。能匹配多 就不匹配少

基础

1、两种使用方式。构造函数和对象字面量

// 构造函数 规则为变量时,推荐使用(动态声明规则)
const reg = new RegExp('规则', '修饰符属性');
// 对象字面量 通常使用这种方式声明正则
const reg = /规则/修饰符属性;

2、修饰符属性

i:是否大小写 ignore case
g:是否全局匹配,否则只返回第一个匹配成功的字符 global
m:是否换行匹配 multi-line

3、匹配方式:
匹配的是大小写敏感且连续的字符串片段。
规则中一位代表匹配字符串中的一位
只要匹配成功,后面的内容就不会在匹配,否则会一次匹配。

const reg = /[0-9][0-9][0-9]/g;
const str = '09e000u00e000';
console.log(str.match(reg)); 
// [000, 000]

4、表达式 [] 一个[]代表匹配一位

const reg = /test/;
const str = 'this is a test';
console.log(str.match(reg));
// [test]

// 理解 取的是每一个[]的任意一项,也就是每一个[]进行组合匹配,就会有 wxz,wyz,xxz,xyz,所以就会匹配出xyz
const reg1 = /[wx][xy][z]/;
const str1 = 'wxyz';
console.log(str1.match(reg1));
// [xyz]

5、[] 区间 用 - 代表区间;匹配的顺序要按照ASCII值。比如[a-Z]就是不对的 a > Z,因为超出了ASCII值的范围

const reg = /[0-9]/;
/*
符合的区间
[0-9A-Za-z]
[0-9A-z]
[0-Z]
[0-z]
[^0] 第一位是0
^[0] 第一位非0
*/

6、元符号 一个元符号代表一位

/*
\w === [0-9A-z_]
\W === [^\w]
\d === [0-9]
\D === [^0-9]
\s === [\r\n\t\r\f] // 转义符号
\S === [^\s]
\b 单词边界 字符串开头与结尾,完整单词左右,单个字符(不包括符号)左右位置
\B 非单词边界 [^\B]
. 除了回车和换行的所有字符
*/
const reg = /\wab/g;
const str = '0abdf';
console.log(str.match(reg)); // ['0ab']

7、转义符号

\t     制表符 tab键
\n    换行符
\r     回车符
\v    垂直换行
\f     换页符

进阶一

量词
1、+ 一次到正无穷 {1, 正无穷}

const reg = /\w+/g;
const str = 'abcgsjfhas';
console.log(str.match(reg)); //  [ 'abcgsjfhas' ]
const str1 = 'abcgs+jfhas';
console.log(str1.match(reg)); //  [ 'abcgs', 'jfhas' ]

2、* 0次到正无穷 {0, 正无穷} 比 + 多匹配出一个空

const reg = /\w*/g;
const str = 'abcgsjfhas2345';
console.log(str.match(reg)); // [ 'abcgsjfhas2345', '' ]
// 之所以会有一个空字符串 是因为最后没有匹配到是0 所以返回空字符串

3、? 0到1 {0,1}

// 因为是 0个或1个 所以就是一个字符一个字符匹配。
const reg = /\w?/g;
const str = 'abcgsjfhas2345';
console.log(str.match(reg)); // ['a', 'b', 'c', 'g', 's','j', 'f', 'h', 'a', 's', '2', '3', '4', '5', '']

4、{x,y} x到y个 之间不能有空格

// 匹配1个或两个 因为贪婪模式所以默认按最多显示数匹配
const reg = /\w{1,2}/g;
const str = 'abcgsjfhas2345';
console.log(str.match(reg)); // [ 'ab', 'cg', 'sj', 'fh', 'as', '23', '45']

5、^n 匹配任何以n开头的字符串

// 匹配以ab开头字符串
const reg = /^ab/g;
const str = 'abcgsjf+abhas2345';
console.log(str.match(reg)); // [ 'ab' ]

6、n$ 匹配任何以n结尾的字符串

// 匹配以45结尾字符串
const reg = /45$/g;
const str = 'abcgsjf+abhas2345';
console.log(str.match(reg)); // [ '45' ]

7、问题:检查字符串是否以abcd开头以abcd结尾

// 中间要匹配任意字符
const reg = /^abcd.*abcd$/g;
const str = 'abcd1234124abcd';
console.log(str.match(reg)); // [ 'abcd1234124abcd' ]
// 任意字符 可以用 [\s\S]
// ^abcd& 这样写是不对的(原因 结束是开头的字符串  但是两者是不同的)

8、正向预查、不捕获分组
查找一个字符串 后面紧跟什么的字符串, 注意要通过()括起来当做表达式使用

  • ?=n 匹配任何其后紧跟着指定字符串n的字符串
  • ?!n 匹配任何其后不紧跟着指定字符串n的字符串
  • ?:n 不捕获其后字符
// 查找ab后紧跟c的ab字符串
const reg = /ab(?=c)/g;
const str = 'abcdabcd';
console.log(str.match(reg)); // ['ab', 'ab']
// 不捕获分组
const reg = /(?:a)(b)(c)/;
const str = 'abcabc';
console.log(str.match(reg));
/**
* ['abc', 'b', 'c', index: 0, input: 'abcabc', groups: undefined]  就是子表达式不显示出来
* 正常下 ['abc', 'a', 'b', 'c', index: 0, input: 'abcabc', groups: undefined] 正常 a 是捕获出来的
*/

9、子表达式()与反向引用 \1
子表达式:有记忆性的,与反向引用一起用时, 每一次反向引用, 引用记忆的那个字符。
反向引用: \1 反向引用第几个子表达式(从1开始), 要引用几次就写几个\1

// 匹配 xxxx
const reg = /(\w)\1\1\1/g;
const str = 'bbcccccaasssffff';
console.log(str.match(reg)); //  ['cccc', 'ffff']
// 匹配 xxyy
const reg = /(\w)\1([A-z])\2/g;
const str = 'bbcccccaasssffff';
console.log(str.match(reg)); // ['bbcc', 'ccaa', 'ssff']

10、对象属性与方法

// 属性
const regObj = /(\w)\1([A-z])\2/g;

// 是否设置修饰符属性
regObj.global;
regObj.ignoreCase;
regObj.multiline;

// 表达式体
regObj.source;

// 下标位置  可通过lastIndex 修改下标位置 并影响exec中的index
// 但是 lastIndex 修改的不是exec匹配的,exec会寻找与当前下标相近的可匹配的下标。
regObj.lastIndex;

// 方法
// 返回TRUE or FALSE
regObj.test(String);

// 返回的是类数组  但是可以连续匹配 是一轮一轮匹配  循环匹配的 直到匹配到null
// lastIndex 与 exec中index是吻合的
// exec 匹配反向引用子表示,会把子表示每次引用的字是什么返回出来
regObj.exec();

const regExec = /123/g;
const strExec = '123123324122';
console.log(regExec.exec(strExec)); 
// ['匹配出来的数据, '开始匹配的下标', '被匹配的字符串']
// [ '123', index: 0, input: '123123324122', groups: undefined ]

const regExec = /(\w)\1(\w)\2/g;
const strExec = 'bbcccccfffcccsss';
console.log(regExec.exec(strExec)); 
// ['匹配出来的数据, '子表达式1数据', '子表达式2数据', '开始匹配的下标', '被匹配的字符串']
// ['bbcc', 'b', 'c', index: 0, input: 'bbcccccfffcccsss', groups: undefined]

进阶二

replace
参数1:字符串或正则
参数2:字符串或回调函数

// JSScript 将Script 去除
const repStr = 'JSScript';
const result = repStr.replace(/Script/g, '');
console.log(result); // JS

将格式为 xxyy 翻转为 yyxx

// 字符串格式
const repStr = 'aabbccddffgg';
const repReg = /(\w)\1(\w)\2/g;
// $1 $2 分别代表子表达式1和2
const result = repStr.replace(repReg, '$2$2$1$1');
console.log(result); // 'bbaaddccggff'
// 回调函数
const result1 = repStr1.replace(repReg, ($, $1, $2) => {
    // $ 为被匹配的数据 aabb
    // $1 为第一个子表达式 a
    // $2 为第二个子表达式 b
    // console.log($, $1, $2);
    return $2 + $2 + $1 + $1;
});
console.log(result1); // 'bbaaddccggff'

js-script 改为 jsScript

// 字符串
const repStr = 'js-script';
// 子表达式为 -s
const result = repStr.replace(/(\-\w)/g, 'S');
console.log(result); // 'jsScript'
// 回调函数 
// 子表达式为 s
const result1 = repStr2.replace(/-(\w)/g, ($, $1) => {
   return $1.toUpperCase();
});
console.log(result1); // 'jsScript'

xxyyzz -> XxYyZz

const repStr = 'xxyyzz';
const result7 = repStr4.replace(/(\w)\1(\w)\2(\w)\3/g, ($, $1, $2, $3) => {
    return $1.toUpperCase() + $1 + $2.toUpperCase() + $2 + $3.toUpperCase() + $3;
});

aabbcc -> a$b$c$ 不能用function

const repStr = 'aabbcc';
// $是特定 如果想用$ 连写两个$$
const result = repStr.replace(/(\w)\1(\w)\2(\w)\3/g, '$1$$$2$$$3$$');
console.log(result); // a$b$c$ 

aa\bb\cc 匹配 \

const repStr = 'aa\\bb\\cc';
// \是特殊符号要用转义符,
const repReg = /(\\)+/g;
console.log(repStr.match(repReg)); // ['\\', '\\']

aabbcc -> abc 等个字符串去重

const repStr = 'aabbcc';
const result = repStr.replace(/(\w)\1(\w)\2(\w)\3/g, '$1$2$3'); 
console.log(result); // abc

aaabbbbbcccccc -> abc 不等个字符串去重

const repStr = 'aaabbbbbcccccc';
// * 是对于反向引用 \1 来说的
const result = repStr.replace(/(\w)\1*/g, '$1');
console.log(result); // abc

数字千分位逗号隔开

// 10000000000 变成 1,000,000,000
// 1、从左往右截取 缺点:如果最后不是3位时 100,000,000,00 是不对的
const repStr = '1000000000';
// \B 非单词边界 每3位的最后为非单词边界,但是整个字符串的开始与结束未单词边界,所以最后正好为3位时也不会加上,
const result = repStr.replace(/(\d{3}\B)/g, ($, $1) => {
    return $1 + ','
});
// 2、推荐 从右往左截取
/**
* 用正向预查  以3位3位为结尾的 每次匹配出来的都是空  前面是个空
* 每次都是以空位开始,后面紧跟3个数字位结尾,还得是个非单词边界
*/
const repReg = /(?=(\B)(\d{3})+$)/g;
const result1 = repStr.replace(repReg, ','); // 1,000,000,000
// 方案2中正则可用于诸如类似与每几位字符串之间添加字符的案例。
// 如 abaskfaksdfajfhadjbfadf  每4位之间加一个-
const repStr2 = 'abaskfaksdfajfhadjbfadf';
const result2 = repStr2.replace(/(?=(\B)(\w{4})+$)/g, '-');

模板匹配 {{}}

const obj = {
    name: '李华',
    age: 34
};
const repStr = 'My name is {{name}}, I am age is {{age}}。';
// .*? 必须加括号变成子表达式,这样才能在replace获取到
const repReg = /\{\{(.*?)\}\}/g;
const result = repStr14.replace(repReg, ($, $1) => {
    return obj[$1];
});
console.log(result);
// My name is 李华, I am age is 34。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值