一、正则基础
转义:转换意义 改变意义
-
转义符号:
\
-
转义字符:
\字符
-
RegExp: Regular expression
-
var reg = new RegExp(要匹配的字符串,是否忽略大小写);
- RegExp参数:
- 参数1:要匹配的字符串str
- 参数2:i g
- RegExp参数:
var reg = new RegExp('Test', 'igm'); // 可以用变量代替正则内容
var reg2 = /^Test/igm; // 直接量方式 不可使用变量代替正则内容
var str = 'this is test. Test is important.';
reg.test(str); // true
str.match(reg); // [test, Test]
- 注意事项
var reg = /Test/igm;
var reg2 = RegExp(reg); // reg跟reg2 是同一个引用
var reg3 = new RegExp(reg); // reg跟reg3 不是同一个引用
1、正则修饰符(正则属性)
i
ignoreCase:忽略大小写g
global:全局匹配m
mutli-line:多行匹配
2、元字符(正则使用的转义字符)
-
\w
word ===[0-9A-z_]
-
\W
===[^\w]
非\w (除了数字字母下划线的字符) -
\d
digit数字 ===[0-9]
-
\D
===[^\d]
(除了数字的字符) -
\s
space制表符 ===[\r\n\t\v\f]
\r:回车 \v:垂直换行 \f:换页符 \n换行 \t制表
-
\S
===[^\s]
-
\b
bridge桥 ===单词边界
-
\B
===非
单词边界 -
.
匹配所有的除了回车\r
和换行\n
的所有字符
3、量词
n+
:{1, 正无穷}
贪婪模式(能匹配多个,绝不匹配少个)
var reg = /\w+/g,
str = 'abcasga';
str.match(reg); // ['abcasga']
n*
:{0, 正无穷}
比n+
多了一个空字符串
var reg = /\w*/g,
reg2 = /\d*/g,
str = 'abcasga';
str.match(reg); // ['abcasga', '']
str.match(reg2); // ['','','','','','','',''] 8个''
// 字符串从左到右,依次先匹配多,再匹配少,如果一但匹配上就不回头
n?
: 出现0或1次
var reg = /\w?/g,
str = 'abcasga';
str.match(reg); // ['a','b','c','a','s','g','a','']
n{x,y}
:{1,正无穷} === n+
{0,正无穷} === n*
var reg = /\w{1,2}/g,
reg2 = /\w{1,}/g,
reg3 = /\w{0,2}/g,
reg4 = /\w{0,}/g,
str = 'abcasga';
str.match(reg); // ['ab', 'ca', 'sg', 'a']
str.match(reg2); // ['abcasga']
str.match(reg3); // ['ab', 'ca', 'sg', 'a', '']
str.match(reg4); // ['abcasga', '']
-
^n
: 匹配任何以n开头的字符串 -
n$
: 匹配任何以n结尾的字符串
// 匹配以lyb开头并且以lyb结尾的
var reg = /^lyb[\s\S]*lyb$/g; // [\s\S]* 代表多个任意字符(*代表0个或多个)
var reg = /^lyb.*lyb$/g; // .代表任意字符 .*代表多个任意字符 (+代表1个或多个。\d+ 数字出现一次或多次)
?=n
: 匹配任何其后紧跟着指定字符串n的字符串var str = 'abcddabgacd', reg = /ab(?=g)/g; str.match(reg) // ['ab']
?!n
: 匹配任何其后不跟指定字符串n的字符串
4、子表达式、反向引用
匹配xxxx、 xxyy形式的 (子表达式、反向引用)
- 子表达式:
()
存在记忆功能 - 反向引用:
\1
\2
反向引用第1或2个子表达式// 找出四个连着的a var str = 'bbaaaaggggaaaaggaaa', reg = /(a)\1\1\1/g str.match(reg) // ['aaaa', 'aaaa'] // 匹配四个相同的字符 reg = /(\w)\1\1\1/g
- 匹配
xxxx
、xxyy
形式的:reg = /(\w)\1(\w)\2/g
5、正则属性
reg.global
true/falsereg.ignoreCase
true/falsereg.multiline
true/falsereg.source
正则本体
案例
1、检测字符串是否以abcd开头bcd结尾
1.检测字符串是否以abcd开头bcd结尾
var str = 'abcdeqwrgjeo234524abcd',
reg = /^abcd[\s\S]*bcd$/;
或 reg = /^abcd.*bcd$/;
2、检测字符串是否以abcd开头bcd结尾,并且中间是数字
var str = 'abcd234253245bcd',
reg = /^abcd\d+abcd$/;
或 reg = /^abcd[\d]+abcd$/;
3、检测手机号是135开头的11位手机号
var str = '13533332222',
reg = /^135\d{8}/g;
4、不允许输入特殊字符,只能数字字母下划线、
var reg = /[^A-z0-9_]+/
str.replace(reg, '');
5、身份证验证
var reg = /^[1-9]\d{5}(18|19|20|21)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[1-9Xx]$/
6、匹配用户名:至少六位 包含一个大写、一个小写、一个数字、一个特殊
正向预查:
`var reg = /^.*(?=.{6,})/` 开头是以任意字符出现多次6位以上
`var reg = /^.*(?=.{6,})(?=.*\d)/` 任意字符(除了回车和换行符)出现多次的数字
`var reg = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[~!@#$%^&*?]).*$/` 以任意字符结尾.*$
7、匹配正整数、负整数、整数
var reg1 = /^\d+$/ 正
var reg2 = /^-\d+$/ 负
var reg3 = /^-?\d+$/ 整数
8、匹配邮箱
var reg = /^([A-z0-9_-])+\@([A-z0-9_\-\.]+\.([A-z]{2,4}))$/
9、匹配座机号
// +86、 086-028-434355345-132
var str = '086-028-43435345-132'
reg = /^(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?$/
10、匹配日期
// 1990-12-01 1990/12/01 1990.12.01
var str = '1990-12-01',
reg = /^(19|20)\d\d([-/.])(0[1-9]|1[0-2])\2([0[1-9]|[12][0-9]|3[01])/
11、匹配微信号
var reg = /^[A-z]([A-z0-9_-]{5,19})+$/
4、正向预查(先行断言、先行否定断言)
/x(?=y)/
5、正则对象方法
test方法
正则表达式下面的test方法:
- 用来判断这个字符串是否满足该正则表达式
- 参数:
- 参数1:要匹配的字符串
- 参数2:ignore case 是否忽略大小写
reg.test(str)
exec方法
exec() 执行
-
该方法返回一个类数组,但是他继承
Array.prototype
-
一轮一轮匹配,改变下标。(必须全局匹配
g
) -
lastIndex
属性跟匹配到的数组中的index
一样 -
可以通过lastIndex来调整鼠标指针(匹配的轮数索引)
-
会把反向引用的每一次引用的子表达式给找出来
match方法
- 接收一个正则规则,返回匹配后的元素组成的数组
二、正则进阶
1、正向预查
- 查询一个字符串并且是有条件的
var str = 'agabaaagag',
reg = /a(?=b)/g;
reg = /a(?!b)/g
str.match(reg) // ['a']
2、贪婪模式、非贪婪模式
.
匹配除了换行符跟行结束符*
匹配0次或者多次任意字符
var str = 'gaga{{fafasg}}gag{{dgab}}',
reg = /{{.*}}/g;
str.match(reg) // ['{{fafasg}}gag{{dgab}}']
- 如上例子,正则默认是贪婪模式匹配,只要能匹配多,那么就不匹配少。
var str = 'gaga{{fafasg}}gag{{dgab}}',
reg = /{{.*?}}/g;
str.match(reg) // ['{{fafasg}}', '{{dgab}}']
- 在后边加
?
,将改为非贪婪模式
。 - 如果是把*号去掉:
/{{.?}}//
这样匹配,,那么就是匹配0到1次
var str = 'aaaaa',
reg = /\w?/g; // 含义: \w? 出现 1次跟0次
// 能多匹配就多匹配 贪婪模式
str.match(reg); // ['a', 'a', 'a', 'a', 'a', '']
var str = 'aaaaa',
reg = /\w??/g; // 含义 \w?? 出现 0次
// 能少匹配就少匹配 非贪婪模式
str.match(reg); // ['', '', '', '', '', ''] 匹配0次
3、捕获分组、不捕获分组
var str = 'abcabc',
// 捕获分组
str1 = str.match(/(b)(c)/), // bc, b, c
str2 = str.match(/(a)(b)(c)/), // abc, a, b, c
// 不捕获分组
str3 = str.match(/(?:a)(b)(c)/), // abc, b, c
4、字符串方法 replace
-
replace不具备全局匹配能力
var str = 'JSplusplus', str1 = str.replace('plus', '+') // JS+plus var str = 'JSplusplus', reg = /plug/, str2 = str.replace(reg, '+') // JS+plus var str = 'JSplusplus', reg = /plug/g, str2 = str.replace(reg, '+') // JS++
-
将字符串xxyy 变位 yyxx
var str = 'aabbxxyy', reg = /(\w)\1(\w)\2/g str.replace(reg, '$2$2$1$1') // 'bbaayyxx' str.replace(reg, function($, $1, $2) { return $2 + $2 + $1 + $1; }) // 'bbaayyxx'
-
将字符串 js-plus-plus 变为 jsPlusPlus
var str = 'js-plus-plus', reg = /-(\w)/g str.replace(reg, function($, $1) { return $1.toUpperCase() })
-
将字符串去重 aaaabbbbbccc 变为abc
var str = 'aaaabbbbbccc', reg = /(\w)\1*/g str.replace(reg, '$1')
-
利用正向预查实现金额千分符分割
var str = '345363246', // ?= 正向预查 \B非单词边界 \d{3} 数字出现3次 + 1次或多次 $ 以他结尾 // 空的 正向预查 单词边界 以3个数字出现1次或多次结尾 reg = /(?=(\B)(\d{3})+$)/g; str.replace(reg, ',')
三、ES6新的扩展
- 声明正则的变化方式
- 字符串上的正则方法进行了调整
- 新增的修饰符:u y s
1、声明正则的变化方式
- ES5声明正则:
var reg = new RegExp('xyz', 'ig');
var reg2 = /xyz/ig;
var reg3 = new RegExp(/xyz/gi);
var reg4 = new RegExp(/xyz/, 'gi'); // ES5之前这种方式报错,不支持;ES6支持
var reg5 = new RegExp(/xyz/g, 'mi'); // ES6忽略了第一个参数的修饰符
var str = 'xyzasdgjadsjxyz';
console.log(str.match(reg));
console.log(str.match(reg2));
console.log(str.match(reg3));
2、字符串上的正则方法进行了调整
String.prototype.match
实际是在调用RegExp.prototype[Symbol.match]
- ES6将字符串中能够通过正则处理的方法定义到了
RegExp.prototype
上
这些方法有:match、replace、search、split
3、新增的修饰符:u y s
sticky(y修饰符)
y: sticky粘连
var reg = new RegExp('xyz', 'igy');
// 每一个修饰符 对应 一个属性
reg.global; // true
reg.ignoreCase; // true
reg.multiline; // false
reg.sticky; // true
var str = 'aaaa_aa_a';
var r1 = /a+/g,
r2 = /a+/y;
console.log(r1.exec(str));//['aaaa', index: 0, input: 'aaaa_aa_a', groups: undefined]
console.log(r2.exec(str));//['aaaa', index: 0, input: 'aaaa_aa_a', groups: undefined]
console.log(r1.exec(str));//['aa', index: 5, input: 'aaaa_aa_a', groups: undefined]
console.log(r2.exec(str));//null
console.log(r1.exec(str));//['a', index: 8, input: 'aaaa_aa_a', groups: undefined]
console.log(r2.exec(str));//['aaaa', index: 0, input: 'aaaa_aa_a', groups: undefined]
console.log(r1.exec(str));//null
console.log(r2.exec(str));//null
// 继续新的一轮匹配
console.log(r1.exec(str));//['aaaa', index: 0, input: 'aaaa_aa_a', groups: undefined]
console.log(r2.exec(str));//['aaaa', index: 0, input: 'aaaa_aa_a', groups: undefined]
- g:贪婪模式匹配不会在往回看,会接着匹配剩余的所有内容
- y:从剩余位置开始,会去确认当前的字符串是否和我们匹配的值是一样的,或者说我们匹配到的值中间是否是连续的
第一个值必须要粘上第二个值才行,第二个匹配方式必须是紧贴上第一个方式才能匹配到
- RegExp.prototype.flags
- RegExp.prototype.source
var reg = /\wabed/giy;
console.log(reg.flags); // giy
console.log(reg.source); // \wabed
u修饰符
- 码点:UTF-16编码
- Unicode:字符编码的总集
- Unicode:分区定义
2*16(BMP)个
-》 17个平面 - U+0000 ~ U+FFFF是物理极限范围,超过之后需要用4个字节表示,替代5位码点2个字节
- U+D800 U+FFFF并没有对应的字符和码点对应,需要用四个字节表示一个字符⭐
// JS引擎不能解析5位码点,加{}之后才可以解析
console.log('\u{20bb7}');
// 用四个字节表示一个字符
console.log('\uD842\uDFB7');
// D800以上,应该是四个字节表示一个字符,匹配的时候也得四个字节一起匹配
console.log(/^\uD83D/u.test('\uD83D\uDC2A'));
var s = '\uD842\uDFB7';
console.log(s);
// . 不能匹配超过极限的字符
console.log(/^.$/.test(s)); // false
console.log(/^.$/u.test(s)); // true
var str = 'aaaa_aa_a';
// {}表示量词
console.log(/a{2}/.test('aa')); // true
console.log(/\u{20bb7}/u.test('吉𠮷')); // true
dotAll代表所有一切(s修饰符)
\n \r U2028 U2029
是.
不能表示的\s
可以表示一切
/foo.bar/s.test('foo\nbar');
console.log(/foo.bar/s.dotAll); // true
四、字符串方法
toString\valueOf的区别
- toString: 将对象转换位字符串
- valueOf: 输出对象原本的值
区别:
- Date
toString 表示时间的特有的字符串
valueOf 13位毫秒时间戳 - 数组
toString 数组元素用逗号分割的字符串
valueOf 数组原本的值 - 对象
toString 对象的类型字符串表示 [obejct Object]
valueOf 对象原本的值 - toString function 通过 [native code] 区别JS内置函数和自定义函数
- toString 接受一个参数-基数 redix; valueOf 没有参数
检测类型封装函数
/**
* @name: 工具类集合
* @author: lybinweb
* @version: v1.0
* @description: ..
* @dateTime: 2022/1/14
*/
let commonTools = {
nbTypeOf: function(val) {
let type = typeof(val),
toStr = Object.prototype.toString;
let resSet = {
'[object Object]': 'object',
'[object Array]': 'array',
'[object Boolean]': 'obj_boolean',
'[object String]': 'obj_string',
'[object Number]': 'obj_number',
'[object Date]': 'date',
'[object RegExp]': 'regexp'
};
if(val === null) {
return 'null';
}else if(type === 'object') {
let res = toStr.call(val);
return resSet[res];
}else {
return type;
}
}
}