正则表达式
闲着无聊,系统的研究一下正则表达式
正则历史的讲解就算了,没有那么博学,直接上基础知识点吧.
正则表达式的文字模板是有很多不同类型的字符组成的,包括:元字符,转义字符,限定符,字符组,或结构,括号分组
1.元字符
字符 | 含义 |
. | 匹配除了换行符(n)以外的所有字符 |
w | 匹配字母,数字,或则汉字 |
W | 匹配除了字母,数字,汉字以外的其他字符 |
d | 匹配数字 |
D | 匹配除了数字以外的其他字符 |
s | 匹配任意的空白符(f,n,r,t,v) |
S | 匹配空白符以外的任意字符 |
b | 匹配单词的开始或则结束 |
B | 匹配单词的非开始或则结束 |
^ | 匹配行首 |
$ | 匹配行尾 |
2.转义字符
*+?|{[()]}^$.#和空白 这些字符都是需要转义的,如果我们要匹配{,就要使用\{
3.限定符
字符 | 含义 |
* | 匹配零次至多次 |
+ | 匹配一次至多次 |
? | 匹配零次或一次 |
{2,} | 至少匹配两次 |
{10} | 匹配10次 |
{2,8} | 至少匹配两次,至多匹配八次 |
4.字符组
中括号字符组用来匹配括号内的字符之一. 例
'fasfagxfasdfyfasfz'.split(/[xyz]/) //["fasfag", "fasdf", "fasf", ""]
还有一种排除性字符组
'xaxbycz'.split(/[^xyz]/) //["x", "x", "y", "z"]
或结构|
例如c|d匹配c或则d
/c|d/.test('af') // false /c|d/.test('ad') // true
括号分组
(cd){1,} 可以匹配cdcd..等, 其中cd便是一个分组
/(cd){1,}$/.test('cdcd') //true
5.贪婪模式和非贪婪模式
默认情况下,所有的限定词都是贪婪模式,表示尽可能多的去捕获字符.而在限定词后增加'?',则是非贪婪模式,表示尽可能少的去捕获字符
'ccccccd'.match(/c+/) //["ccccc"], 贪婪模式, 捕获所有 'ccccccd'.match(/c+?/) //["c"], 非贪婪模式, 只捕获到第一个
6.捕获分组
在实际应用中我们很有可能需要获取到匹配的字符串,例如我们要将字符串"万里碧空飘着朵朵白云"替换成"万里碧空没有一朵白云"
"万里碧空飘着朵朵白云".replace(/(万里碧空)飘着朵朵白云/, '$1没有一朵白云')
注:
反斜杠+number这种引用可以在正则表达式中使用,可用于匹配不同位置的相同子串,例如:
'www.bai.bai.com'.replace(/([a-z]+)\.\1/, '$1') // www.bai.com
非捕获性分组
非捕获性分组,通常由一对括号加上”?:”加上子表达式组成,非捕获性分组不会创建反向引用,就好像没有括号一样。捕获性分组和无捕获性分组在搜索效率方面也没什么不同,没有哪一个比另一个更快。
/^(?:\d+)/
一、正则表达式的方法
1.test
检索字符串中的指定子串,返回布尔值
/^\d[a-zA-Z]{3}$/.test('1aac') // true
2.exec
返回一个数组,数组中的第一个条目是第一个匹配
/^\d[a-zA-Z]{3}$/.exec('1aac') // ["1aac"]
二、String可以使用正则表达式的方法
1.search
返回子串的开始位置,
'a12b2334c34'.search(/\d{4}/) // 4
2.match
返回匹配到的子串,返回出来的是数组
'a12b2334c34'.match(/\d{4}/) // ["2334"]
'sld12345s1515f'.match(/\d{4}/g) //["1234", "1515"]
3.replace
替换匹配到的子串,返回值为替换过的子串
'a12b2334c34'.replace(/\d{4}/, 'cccc') // "a12bccccc34"
4.split
将字符串分割成数组,返回值为分割成的数组
'a12b2334c34'.split(/\d{4}/) // ["a12b", "c34"]
三、断言
1.正向先行断言 (?=exp)
代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配 exp
/f(?=234)/.test('123abcf234acd') //true
2.负向先行断言(?!exp)
代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配 exp
/f(?!234)/.test('123abcf234acd') //false
四、常用的正则表达式
1.Email地址:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2.URL验证
[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
3.手机号码验证
/^((1[3-8][0-9])+\d{8})$/
4.汉字验证
^[\u4e00-\u9fa5]{0,}$
5.手机号码中间四位替换****
var str = '15500000000'; var str0 = str.replace(/^(\d{3})\d{4}(\d{4})/g,'$1****$2'); console.log(str,str0); //15500000000 155****0000
6.校验身份证号码
15位:
^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$
18位:
^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$
7.校验日期
“yyyy-mm-dd“ 格式的日期校验,已考虑平闰年。
^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$
8.校验金额
金额校验,精确到2位小数。
^[0-9]+(.[0-9]{2})?$
9.一些填写卡号效果
<input type="text" name="code" id="code" />
$('#code').bind('input propertychange', function() { //绑定的方法 var val = $(this).val(), val = val.replace(/-/g, ''), //如果用户输入-,则替换为空 valArr = val.split(''), newVal = ''; for(var i = 0, len = valArr.length - 1; i <= len; i++) { newVal += valArr[i] + ((i && (i % 4 == 3) && i != len) ? '-' : ''); } //处理 $(this).val(newVal.toUpperCase()); //将小写转换成大写 set_text_value_position('code', -1); //强制光标在最后面的函数 }); //封装的强制光标在最后面的函数 function set_text_value_position(obj, spos) { var tobj = document.getElementById(obj); if(spos < 0) spos = tobj.value.length; if(tobj.setSelectionRange) { //兼容火狐,谷歌 setTimeout(function() { tobj.setSelectionRange(spos, spos); tobj.focus(); }, 0); } else if(tobj.createTextRange) { //兼容IE var rng = tobj.createTextRange(); rng.move('character', spos); rng.select(); } }
10.数字格式化: 1234567890 --> 1,234,567,890
非正则的实现:
let test = '1234567890' function formatCash(str) { let arr = [] for (let i = 1; i < str.length; i++) { if (str.length % 3 && i == 1) arr.push(str.substr(0, str.length % 3)) if (i % 3 === 0) arr.push(str.substr(i - 2, 3)) } return arr.join(',') } console.log(formatCash(test)) // 1,234,567,890
用正则实现:
let test1 = '1234567890' let format = test1.replace(/\B(?=(\d{3})+(?!\d))/g, ',') console.log(format) // 1,234,567,890
下面简单分析下正则/\B(?=(\d{3})+(?!\d))/g
:
/\B(?=(\d{3})+(?!\d))/g
:正则匹配边界\B
,边界后面必须跟着(\d{3})+(?!\d)
;(\d{3})+
:必须是1个或多个的3个连续数字;(?!\d)
:第2步中的3个数字不允许后面跟着数字;(\d{3})+(?!\d)
:所以匹配的边界后面必须跟着3*n
(n>=1)的数字。
11.去掉字符串左右两边的空格
非正则实现:
function trim(str) { let start, end for (let i = 0; i < str.length; i++) { if (str[i] !== ' ') { start = i break } } for (let i = str.length - 1; i > 0; i--) { if (str[i] !== ' ') { end = i break } } return str.substring(start, end - 1) } let str = " jaw il " console.log(trim(str)) // "jaw il"
正则实现:
function trim(str) { return str.replace(/(^\s*)|(\s*$)/g, "") } let str = " jaw il " console.log(trim(str)) // "jaw il"
12.字符串数组去重 ['a','b','c','a','b','c'] --> ['a','b','c']
这里只考虑最简单字符串的数组去重,暂不考虑,对象,函数,NaN等情况,这种用正则实现起来就吃力不讨好了。
非正则实现:
//es6实现 let str_arr=["a","b","c","a","b","c"] function unique(arr){ return [...new Set(arr)] } console.log(unique(str_arr)) // ["a","b","c"]
//es5实现 var str_arr = ["a", "b", "c", "a", "b", "c"] function unique(arr) { return arr.filter(function(ele, index, array) { return array.indexOf(ele) === index }) } console.log(unique(str_arr)) // ["a","b","c"]
//es3实现 var str_arr = ["a", "b", "c", "a", "b", "c"] function unique(arr) { var obj = {}, array = [] for (var i = 0, len = arr.length; i < len; i++) { var key = arr[i] + typeof arr[i] if (!obj[key]) { obj[key] = true array.push(arr[i]) } } return array } console.log(unique(str_arr)) // ["a","b","c"]
正则实现:
var str_arr = ["a", "b", "c", "a", "b", "c"] function unique(arr) { return arr.sort().join(",,"). replace(/(,|^)([^,]+)(,,\2)+(,|$)/g, "$1$2$4"). replace(/,,+/g, ","). replace(/,$/, ""). split(",") } console.log(unique(str_arr)) // ["a","b","c"]
13.手机号强制输入数字,且不能超过11位
$('#tel').on('input prototychange',function () { $(this).val($(this).val().replace(/\D/g,'')); //将所输入的非数字字符替换为空字符 if ($(this).val() >= 12) { $(this).val($(this).val().slice(0,11)); //如果输入字符大于等于12位,则只取其前11位为其值 } }); //引入jq所写
以后,再补充...