学习正则的网站
博客园正则
https://rubular.com/
https://jex.im/regulex
http://regexr.com/
https://regex101.com/
https://www.regular-expressions.info
https://regexcrossword.com
. 这个表示除了\n以外的任何数据,他和*+?都不同,后边的几个都是表示数量。而.表示字符。
* 匹配前面元字符0次或多次,/ba*/将匹配b,ba,baa,baaa
+ 匹配前面元字符1次或多次,/ba*/将匹配ba,baa,baaa
? 匹配前面元字符0次或1次,/ba*/将匹配b,ba
(x) 匹配x保存x在名为$1...$9的变量中
x|y 匹配x或y
{n} 精确匹配n次
{n,} 匹配n次以上
{n,m} 匹配n-m次
[xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符)
[^xyz] 不匹配这个集合中的任何一个字符
\w 匹配一个字母数字下划线
\W 匹配一个不可以组成单词的字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]
\d 匹配一个字数字符,/\d/ = /[0-9]/
\D 匹配一个非字数字符,/\D/ = /[^0-9]/
\n 匹配一个换行符
\r 匹配一个回车符
\s 匹配一个空白字符,包括\n,\r,\f,\t,\v等
\S 匹配一个非空白字符,等于/[^\n\f\r\t\v]/
js中字符串的match、search、replace、split可以使用正则
test,exec是正则点字符串
/aa/.test('aa')
true
/aa/.exec('aa')
['aa', index: 0, input: 'aa', groups: undefined]
'aa'.match(/aa/)
['aa', index: 0, input: 'aa', groups: undefined]
'aa'.replace方法
'aa'.replaceAll方法
'aa'.split
'aa'.search
var str="Visit Runoob!";
var n=str.search("Runoob");
console.log(n); //6
[]中的^是非的意思,不是开头的意思
\D 匹配一个非字数字符,/\D/ = /[^0-9]/
/g /i /m /e /x /s的用法
1、/g 表示该表达式将用来在输入字符串中查找所有可能的匹配,返回的结果可以是多个。如果不加/g最多只会匹配一个
2、/i 表示匹配的时候不区分大小写,这个跟其它语言的正则用法相同
3、/m 表示多行匹配。什么是多行匹配呢?就是匹配换行符两端的潜在匹配。影响正则中的^$符号
4、/s 与/m相对,单行模式匹配。
5、/e 可执行模式,此为PHP专有参数,例如preg_replace函数。
6、/x 忽略空白模式。
=== 无论是捕获性非捕获性,贪婪与非贪婪 非都是一般不带 g使用,比较明显。带g很容易乱了。
捕获性 和 非捕获性 一般与replace函数一起使用
表达式 含义
() 表示捕获分组,()会把每个分组里的匹配的值保存起来,使用$n(n是一个数字,表示第n个捕获组的内容)
(?:) 表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来
> '111abcd222abcd333abcd'.match(/\d+([a-z])/); 打印 ["111a", "a"] RegExp.$1为a
> '111abcd222abcd333abcd'.match(/(\d+)([a-z])/); 打印 ["111a", "111", "a] RegExp.$1为111,$2为a
> '111abcd222abcd333abcd'.match(/(\d+)(?:[a-z])/); 打印 ["111a", "111"] RegExp.$1为111,$2为''
> '111abcd222abcd333abcd'.match(/(\d+)[a-z]/); 打印 ['111a', '111']RegExp.$1为111,$2为''
想尝试捕获111abcd 222abcd 333abcd
> '111abcd222abcd333abcd'.match(/.(\d+)(?:[a-z])/) 前边加.
['111a', '11']
> '111abcd222abcd333abcd'.match(/.*(\d+)(?:[a-z])/); ["111abcd222abcd333a", "3"] 前边加.*
> '111abcd222abcd333abcd'.match(/.*?(\d+)(?:[a-z])/)
['111a', '111']
> '111abcd222abcd333abcd'.match(/.*(\d+)(?:[a-z]).*/); ["111abcd222abcd333abcd", "3"] 前后都加.*
>'111abcd222abcd333abcd'.match(/.*?(\d+)(?:[a-z]).*/);["111abcd222abcd333abcd", "111"] 前边的.*后边加了?关闭了贪婪捕获
>'111abcd222abcd333abcd'.match(/(\d+[a-z]+)/g) ["111abcd", "222abcd", "333abcd"] 加了一个全局的g就可以了。
贪婪与非贪婪,带g一般开启非贪婪
----没有g的时候其实不会多次匹配的,只会匹配一次
'abcd'.match(/\w/)
结果:['a', index: 0, input: 'abcd', groups: undefined]
// +号会导致匹配多个
'abcd'.match(/\w+/)
结果:['abcd', index: 0, input: 'abcd', groups: undefined]
'abcd'.match(/\w+?/)
结果: ['a', index: 0, input: 'abcd', groups: undefined]
'abcd'.match(/\w*?/)
结果:['', index: 0, input: 'abcd', groups: undefined]
----带g的时候
'abcd'.match(/\w/g)
结果: ['a', 'b', 'c', 'd']
'abcd'.match(/\w*/g)
结果: ['abcd', '']
'abcd'.match(/\w*?/g)
结果: ['', '', '', '', '']
'abcd'.match(/\w+?/g)
结果: ['a', 'b', 'c', 'd']
--- 巧妙了利用8,进行了非贪婪
'--8a8--8b8--8c8'.match(/8([^8]*)8/g)
// [ '8a8', '8b8', '8c8' ]
'--8a8--8b8--8c8'.match(/8([^8]*?)8/g)
// [ '8a8', '8b8', '8c8' ]
'abc8aaa8---8bbb8---8ccc8abc'.match(/8(.+?)8/g)
['8aaa8', '8bbb8', '8ccc8']
'abc8aaa8---8bbb8---8ccc8abc'.match(/8(.+)8/g)
['8aaa8---8bbb8---8ccc8']
前瞻性和 后顾性
正则匹配的前瞻就是给正则匹配的选项定义一个断言,或者说是一个条件比如:我要匹配一个字母,但是我的需求是字母后面必须是跟着一个数字的情况,那么这种场景是怎么实现了,就是用到前瞻的概念,那么我想要他的前面也要是一个数字怎么办了,这就是后顾.
表达式 含义
(?=pattern) 正向肯定查找(前瞻),后面必须跟着什么
(?!pattern) 正向否定查找(前瞻),后面不能跟着什么
(?<=pattern) 反向肯定条件查找(后顾),不捕获
(?<!pattern) 反向否定条件查找(后顾)
console.log(‘1a’.match(/\d(?=[a-z])/));
console.log(‘1@’.match(/\d(?![a-z])/));
console.log(‘a1’.match(/(?<=[a-z])\d/));
console.log(‘$1’.match(/(?<![a-z])\d/));
'23456789'.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') '23,456,789'
'23456789'.replace(/(\d)(?=(?:\d{3})+)/g, '$1,') '2,3,4,5,6,789'
'23456789'.replace(/(\d)(?=(?:\d{3})$)/g, '$1,') '23456,789'
'23456789'.replace(/(\d)(?=(?:\d{3}))/g, '$1,') '2,3,4,5,6,789'
'23456789'.replace(/(\d)((?:\d{3})+$)/g, '$1,') '23,'
mgi
1,/g 表示该表达式将用来在输入字符串中查找所有可能的匹配,返回的结果可以是多个。如果不加/g最多只会匹配一个
2,/i 表示匹配的时候不区分大小写
3,/m 表示多行匹配,什么是多行匹配呢?就是匹配换行符两端的潜在匹配。影响正则中的^$符号
$1 $2
'---8ggg8---9bbb9---'.match(/8(.*?)8---9(.*?)9/g);
console.log(RegExp.$1) // ggg
console.log(RegExp.$2) // bbb
'---8ggg8---8bbb8---'.replace(/8(.*?)8/g, 'tt$1tt')
//---ttgggtt---ttbbbtt---
使用分组嵌套
'abc'.match(/(a?(b?(c?)))/g)
// [ 'abc', '' ]
'abc'.match(/(a(b(c)))/g)
// ['abc']
检查邮政编码
//共 6 位数字,第一位不能为 0
var pattern = /[1-9][0-9]{5}/;
var str = ‘224000’;
alert(pattern.test(str));
检查文件压缩包
var pattern = /[\w]+.zip|rar|gz/;//\w 表示所有数字和字母加下划线
var str = ‘123.zip’;//.表示匹配.,后面是一个选择
alert(pattern.test(str));
删除多余空格
var pattern = /\s/g;
var str = ‘111 222 333’;
var result = str.replace(pattern,‘’);
//把空格匹配成无空格
删除首尾空格
ar pattern = /^\s+/;//强制首
varstr=' goo gle';
var result = str.replace(pattern, '');
pattern = /\s+$/;//强制尾
result = result.replace(pattern, '');
alert('|' + result + '|');
alert(result);
var pattern = /^\s*(.+?)\s*$/;//使用了非贪婪捕获
var str = ' google '; alert('|' + pattern.exec(str)[1] + '|');
var pattern = /^\s*(.+?)\s*$/;//使用了分组获取
var str = ' google '; alert('|' + str.replace(pattern, '$1') + '|');
简单的电子邮件验证
var pattern = /^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9_\.\-]+)\.([a-zA-Z]{2,4})$/; var str = 'yc60.com@gmail.com';
alert(pattern.test(str));
var pattern = /^([\w\.\-]+)@([\w\.\-]+)\.([\w]{2,4})$/; var str = 'yc60.com@gmail.com'; alert(pattern.test(str));
匹配css中的正则
/url\((.+?)\)/g.exec('.box{backgroud:url("./image/aa.png")')
['url("./image/aa.png")', '"./image/aa.png"']
'.box{backgroud:url("./image/aa.png")'.match(/url\((.+?)\)/g)
[ 'url("./image/aa.png")' ]
RegExp.$1 "./image/aa.png"
RegExp.$2 ""
使用m换行模式
var pattern = /^\d+/mg;//启用了换行模式
var str = ‘1.baidu\n2.google\n3.bing’;
var result = str.replace(pattern, ‘#’);
用re = new RegExp(“pattern”,[“flags”]) 的方式比较好
驼峰变-划线
`${attr.replace(/([A-Z])/g,function(){ return"-"+arguments[1]})
匹配{{name}}中的name
const s = '{{name}}';
console.log('---');
if(/\{\{(.*)\}\}/.test(s)) {
const exp = RegExp.$1;
console.log(exp);
}
---
content += templateStr.replace(/\{\%(.+?)\%\}/g, function() {
return "`\r\n" + arguments[1] + "\r\nstr+=`";
});
url的正则
// 正则+replace
let str = 'sadf?key=14&key=24&key=34&test=44';
let result = {};
str.replace(/([^?=&]+)=([^&=]+)/g, function () {
// console.log(arguments[0], arguments[1], arguments[2])
// key=14 key 14
if (!result[arguments[1]]) {
result[arguments[1]] = arguments[2];
} else {
result[arguments[1]] = [].concat(result[arguments[1]], arguments[2])
}
});
// 不带括号的正则效果完全不同
// str.replace(/[^?=&]+=[^&=]+/g, function () {
// // console.log(arguments[0], arguments[1], arguments[2])
// // key=14 5 sadf?key=14&key=24&key=34&test=44
// if (!result[arguments[1]]) {
// result[arguments[1]] = arguments[2];
// } else {
// result[arguments[1]] = [].concat(result[arguments[1]], arguments[2])
// }
// });
// 正则 match
'sadf?key=14&key=24&key=34&test=44'.match(/([^?=&]+)=([^&=]+)/g)
// ['key=14', 'key=24', 'key=34', 'test=44']
// 不带括号正则表达式
'sadf?key=14&key=24&key=34&test=44'.match(/[^?=&]+=[^&=]+/g)
// ['key=14', 'key=24', 'key=34', 'test=44']
// 用exec实现
/([^?=&]+)=([^&=]+)/mg.exec('sadf?key=14&key=24&key=34&test=44')
['key=14', 'key', '14', index: 5, input: 'sadf?key=14&key=24&key=34&test=44', groups: undefined]
// 用exec不带()
/[^?=&]+=[^&=]+/mg.exec('sadf?key=14&key=24&key=34&test=44')
['key=14', index: 5, input: 'sadf?key=14&key=24&key=34&test=44', groups: undefined]
function getParams(url, params) {
let str = '';
// 这里不能用url.match方法
// ?前必须有一个/,类似转义符
url.replace(new RegExp("(?:&|/?)" + params + "=([^&=]+)", ['g']), function() {
console.log(arguments)
str = arguments[1];
})
return str;
}
const id = getParams('xx.com?id=2&isShare=true', 'id')
console.log('id', id) // 2
三个数字加逗号
'23456789'.match(/(\d)(?=(\d{3})+$)/g)
['3', '6']
// 去掉?=
'23456789'.match(/(\d)((?:\d{3})+$)/g)
['3456789']
// 去掉+
'23456789'.match(/(\d)(?=(?:\d{3})$)/g)
['6']
// 去掉?:
'23456789.1123'.match(/(\d)(?=(\d{3})+$)/g) // 如果参数换成23456789与第一个返回的结果同样
['1']
--------------
function formatNumber(num) {
return num.toString().replace(/\d+/, function (n) {
console.log('n===>>', n);
// (\d{3}) 换成 (?:\d{3})
return n.replace(/(\d)(?=(\d{3})+$)/g, '$1,')
})
}
console.log(formatNumber(23456789.123)) // 123,456,789.123
path-to-regexp 正则
let pathToRegExp = require('path-to-regexp');
let regxp = pathToRegExp('/home',[],{end:true});
console.log(regxp);// /^\/home\/?$/i
console.log(regxp.test('/home'));
console.log(regxp.test('/home/2'));
let pathToRegExp = require('path-to-regexp');
let regx2 = pathToRegExp('/home',[],{end:false});
console.log(regx2);// /^\/home\/?(?=\/|$)/i
console.log(regx2.test('/home'));
console.log(regx2.test('/home/'));
console.log(regx2.test('/home//'));
console.log(regx2.test('/home/2'));
let params = [];
let regx3 = pathToRegExp('/user/:id',params,{end:true});
console.log(regx3,params);
/**
/^\/user\/(?:([^\/]+?))\/?$/i
[ { name: 'id', optional: false, offset: 7 } ]
**/