正则用的很普遍,本文仅针对JavaScript。
创建
有两种方式:
1. new RegExp('表达式', '匹配模式'),这种方式的表达式中如果需要转义,转义符需要写两个,如 '\\d'
2. 直接量
常用属性
1. $1 -> $9
返回9个在模式匹配期间找到的,最近保存的部分,只读
2. index
返回第一次成功匹配的开始位置,只读
3. lastIndex
返回最后一次成功匹配的结束位置(下一次匹配开始的位置),可读写。
只有当使用exec() 或 test() 时才会写入。
4. lastMatch
返回最后匹配的字符,只读。
5. input
返回查找的字符,只读。
这里先送上一个例子,我第一次做的时候觉得异常诡异。
var r = /\d/g; alert(r.test('abcd')); // false alert(r.lastIndex); // 0 alert(r.test('ab1')); // true alert(r.lastIndex); // 3 alert(r.test('a1')); // false alert(r.lastIndex); // 0
说明: lastIndex属性实例属性,当一个正则表达式实例多次test或exec时,它的lastIndex每一次都将被改写。
查找
1. 找出 "~!ab@cd#12$%e3^" 中的数字和字母
第一反应,数字应该是[0-9],字母应该是[a-zA-Z]
但是呢,元字符\w其实就能兼顾二者,来看下
var str = '~!ab@cd#12$%e3^', rep = /\w+/g; str.match(rep); //输出 ["ab", "cd", "12", "e3"]
2. 取出 '<a href="http://g.cn">Google</a>' 中的标签,不要innerHTML,即结果为<a href="http://g.cn"></a>
因为是成对出现的,所以需要记住开头匹配的标签名,这里要用到\1, \2这样的索引,表示第一、二个括号匹配的文本
var str = '<a href="http://g.cn">Google</a>', rep = /(<(\w+)[^>]*>)[^<]*(<\/\2>)/g; if(rep.test(str)){ RegExp.$1; RegExp.$3; }
$1 和 $3,表示正则第一个和第三个括号匹配的内容。
3. 紧接着第2题,取出 '<a href="http://g.cn">Google</a>' 中的innerHTML
var str = '<a href="http://g.cn">Google</a>', rep = /<(\w+)[^>]*>([^<]*)<\/\1>/g; if(rep.test(str)){ RegExp.$2 }
4. JS只支持正序环视,而不支持逆序环视
var str = 'jsafter', rep = /js(?=after)/g; rep.exec(str);
如果 str 换成 "jsbefore",就会匹配失败,但是我们可以这么做
var str = 'jsbefore', rep = /js(?!after)/g; rep.exec(str);
5. 非捕获性分组
var str = '#12345', rep = /#(?:\d+)/; if (rep.test(str)) { RegExp.$1; }
6. 神奇的match()方法
var str = 'js1', rep = /(js)1/; str.match(rep);
这样会打印出 ['js1', 'js'],如果正则加上g,也就是全局匹配,则会打印 ['js1']
替换
替换常用replace()方法,如果它的第一个参数是正则表达式,则第二个参数是函数。
如果正则存在反向引用时,函数的参数列表为:
arguments[0]:成功匹配的字符串
arguments[1]:$1
arguments[2]:$2
.......
arguments[arguments.length - 2]:匹配到的位置
arguments[arguments.length - 1]:要匹配的字符串
如果正则不存在反向引用,函数的参数列表为:
arguments[0]:成功匹配的字符串
arguments[1]:匹配到的位置
arguments[2]:要匹配的字符串
1. 把 "<a>g</a>" 替换成 "<b>g</b>"
var str = '<a>g</a>', rep = /<(\w+)[^>]*>([^<]*)<\/\1>/g; str.replace(rep, '<b>$2</b>');
2. "1废话2废话3废话4废话5废话...",...表示无限可能,任意字符,现在需要把第三个"废话"后面的全部删除
var str = '1废话2废话3废话4废话5废话...', rep = /(.*?废话){3}/g; str = str.match(rep)[0];
3. 把类似 0011.0100 前面的、后面的0去掉(特殊情况 .01, 0.01,记得试试这两个)
先分成整数部分和小数部分进行处理
整数可能出现的情况有:
1. n个0开头,然后数字结尾,如001、0010、10、0
2. 空字符,即整体为 .1 的形式
这样的话,我们先看开头的部分,正则应该是0*?,后面的部分怎么处理呢?它可能是0-9中的任何数字。
也许有人会写成\d*,但这样明显不对,如果这个数字是012呢,这个0应该算在开头的正则中,所以继续分类处理:
1. 只有1位数字时,\d
2. 大于1位数字时,[1-9]\d+
3. 这种情况比较特殊,比如 .1,开头的0没匹配上,在这个部分就必须考虑这种情况了,其实就是\d?
合并一下,就是 (\d?|[1-9]\d+),上述整理合并就是0*?(\d?|[1-9]\d+)
接着看小数部分,\.\d+ 这是最原始的正则,如果是.0100的情况,我们只需要.01,后面的0都要去掉,所以该这么写:(\.\d+?)0*。因为小数部分是可有可无的,所以最后应该写成 ((\.\d+?)0*)?
var str = '001.0100', rep = /^0*?(\d?|[1-9]\d+)((\.\d+?)0*)?$/g; rep.test(str); RegExp.$1; RegExp.$3;