构建正则表达式有两种方法
- 通过RegExp对象构造一个实例,new RegExp( ),如var pattern = new RegExp('http')
- 直接书写,在两个反斜杠之间写匹配的字符, 如 var pattern = /http/
这两种方式是等价的。
正则表达式的方法有test exec ,使用方法如reg.test(string)
支持字符串使用,方法有match search split replace ,使用方法如string.match(reg)
常见的字符和标示符等基础常识
解释标志
- i 不区分大小写
- g 全局匹配
- m 多行匹配
位置表示符(锚字符)
- ^ 字符串的开头
- $ 字符串的结尾
- \b 单词边界
- \B 非单词边界
- (?! p ) 先行断言,接下来的字符都不与匹配
- (?= p ) 负向先行断言,接下来的字符都与匹配
var r = /java(?!Script)([A-Z\w*])/;
r.test('java') //false
r.test('javaScript') //false
r.test('javaWdsfc3') //true
var r = /java(?=Script)([A-Z\w*])/;
r.test('java') //false
r.test('javaScript') //true
r.test('javaWdsfc3') //false
转义字符(元字符)
**\w** 所有单词字符 等价于 [a-zA-Z0-9]
**\W** 非单词字符 等价于 [^a-zA-Z0-9]
**\d** 数字 等价于 [0-9]
**\D** 非数字 等价于 [^0-9]
**.** 除了换行符以外的字符
**\s** 任何Unicode空字符
**\S** 任何Unicode非空字符
重复量词
- + 重复1次或多次
- ***** 重复0次或多次
- ? 重复0次或1次
- {n,m} 重复n次到m次
中文的unicode的正则
/[\u4E00-\u9FA5\uf900-\ufa2d]/
特殊字符要用反斜杠\转义
选择、分组、引用
- [] 匹配任意括号内的任意字符
- [^] 匹配任意除括号外的任意字符(否定的思想)
- | 选择
- () 分组
- (?:) 只组合,不引用,即通过\1 \2的形式不能读到这种子模式匹配到的字符
- \n 引用,如/(\d)\1/,\1表示(\d)。当用“()”定义了一个正则表达式组后,正则引擎则会把被匹配的组按照顺序编号,存入缓存。当对被匹配的组进行向后引用的时候,可以用“\数字”的方式进行引用。“\1”引用第一个匹配的后向引用组,“\2”引用第二个组,以此类推。
一些练习的例子
- 去除字符串首尾的空格
var reg = /^\s+|\s+$/g,
string = ' ddcc ';
string.replace(reg, '') //"ddcc"
reg.test(string) //true
- 匹配以137或者158开头的电话号码
var reg = /^137|158\d{8}$/,
string = '15858392890';
reg.test(string) //true
- 邮箱
var reg = /^\w+@\w+\.[a-zA-Z]+$/,
string = 'ltre1234@126.com';
reg.test(string)
- 匹配日期格式yyyy-mm-dd或者yyyy/mm/dd
var reg = /^\d{4}(-|\/)[01]\d\1[0123]\d$/,
string = '2016-02-19';
reg.test(string)
- 去掉文件的后缀名 如www.abc.com/dc/fda.asp变为www.abc.com/dc/fda
var reg = /\.[a-zA-Z]+$/,
string = 'www.abc.com/dc/fda.asp';
string.replace(reg,'')
- 匹配链接文字
var reg = /^<a[\s\S]*>([\s\S]*?)<\/a>$/,
string = '<a href="#">保存</a>';
string.replace(reg,'$1')
- 正则表达式替换有相同结构的变量
var b = ['A','B','C','D'],
string = '<ul><li>$3$</li><li>$1$</li><li>$2$</li><li>$3$</li></ul>',
reg = /\$(\d+)\$/g;
var newb = string.replace(reg, function(i){
return b[i.replace(/\$/g,'')]
})
console.log(newb) //'<ul><li>D</li><li>B</li><li>C</li><li>D</li></ul>'
- 每单词首字大写,其他小写。如china beijing转换为China Beijing
var reg = /\b[a-z]|\s+[a-z]/g,
string = 'china beijing';
string.toLowerCase().replace(reg,function(i){
return i.toUpperCase()
})
//"China Beijing"
- 将123替换成壹贰叁。
var a = ["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"],
string = '340992334',
reg = /\d/g;
string.replace(reg, function(i){
return a[i];
})
replace 的函数参数的规定:
- 第一个参数为每次匹配的全文本($&)。
- 中间参数为子表达式匹配字符串,个数不限.( $i (i:1-99))
- 倒数第二个参数为匹配文本字符串的匹配下标位置。
- 最后一个参数表示字符串本身。
var reg = /^<a[\s\S]*>([\s\S]*?)<\/a>$/,
string = '<a href="#">保存</a>';
string.replace(reg, function(i,ii,jj,v){
console.log('i : '+ i +'; \nii : ' + ii + '; \njj: ' + jj+ '; \nv :'+ v)
})
/*
输出如下:
i : <a href="#">保存</a>;
ii : 保存;
jj: 0;
v :<a href="#">保存</a>
*/
match和exec,有点小混淆
- 先来一些例子
var s = "web2.0 .net2.0",
reg = /(\w+)(\d)\.(\d)/;
reg.exec(s); //["web2.0", "web", "2", "0"]
s.match(reg); //["web2.0", "web", "2", "0"]
var s = "web2.0 .net2.0",
reg = /(\w+)(\d)\.(\d)/g;
reg.exec(s); //["web2.0", "web", "2", "0"]
s.match(reg); //["web2.0", "net2.0"]
var s = "web2.0 .net2.0 javascript6.0",
reg = /(\w+)(\d)\.(\d)/g;
reg.exec(s); //["web2.0", "web", "2", "0"]
s.match(reg); //["web2.0", "net2.0", "javascript6.0"]
match和exec异同
- exec没有找到匹配,则返回null;若找到,返回数组,第一个元素是与正则表达式匹配的字符串,其他的元素是子模式匹配到的字符串(即圆括号匹配到的)。
- match和exec返回的结果均是null或者数组。
- 正则表达式不使用全局g时,exec 与 match 的结果等价。
- 正则表达式使用全局g时,match会返回所有匹配,而exec只会返回第一个匹配。
- 全局g对exec的匹配没有影响。
用正表达式解析url地址
function parseUrl(str){
var s = str || location.href, //默认值为location.href
reg = /^(?:([a-zA-Z]+):)\/{2}(\w+(?:\.\w+)+)(?::(\d+))?(?:\/([^?#]+))?(?:\?([^#]+))?(?:#(.+))?$/, //利用子模式()的形式匹配出各个部分。由于有的部分如: // ? #不是我们要匹配出来的字符,用(?:)的形式,(?:)这个子模式不会被匹配出来。特殊字符需要转义,如?用\?。像url中可能不存在port、hash,所以要加上量词?(0次或者一次)
arr = ['url', 'protocol','host','port','parthname','query','hash'], //对应reg解析出来的子模式
result = {};
// 解析query
reg.exec(s).forEach(function(v,i){
result[arr[i]] = v;
if(arr[i] === 'query'){
var queryObj = {},
temp;
v.split('&').forEach(function(vv,ii){
if(vv){
temp = decodeURIComponent(vv).match(/([^=|&]+)=([^&]*)/); //将vv解码,之所以不用vv.split('=')是因为有的value里面有等号
temp[1] && ( queryObj[temp[1]] = temp[2] );
}
})
result.queryObj = queryObj;
}
})
return result;
}
var s = "http://129.0.0.1:9000/index.html?&user_id=1590099094&plat=android&v=8.3.4#jhashcd";
var s2 = "http://129.0.0.1/index.html?&user_id=1590099094&plat=android&v=8.3.4#jhashcd";
parseUrl(s)
parseUrl(s2)
parseUrl(s)的结果见下图
parseUrl(s2)的结果见下图