一、背景
工作上碰到一个如许的需求:
用正则表达式将一个字符串中的span标签替代为img标签,并将原span标签的内容放到img标签的src中,题目详细描述:点我
看到这个需求,我晓得应当能够用正则表达式,然则由于之前没怎样用,一想到正则表达式就头大,一堆林林总总的特别符号,好像没有规律可循,有点难以明白。不过晓得自身不能逃避,因而自身就去尝试怎样写这个正则表达式来处置惩罚我的需求,上述中提到的题目详细描述,也许就是我思索的历程,题目提出后立马有人解答,看完他们的答案后,忸捏,觉得到自身学问的短缺,再不进修就老了(┬_┬)
二、正则表达式基本
2.1 元字符引见
“^”:^会婚配行或许字符串的肇端位置,偶然还会婚配全部文档的肇端位置。
“$”:$会婚配行或字符串的末端。
“b”:不会斲丧任何字符只婚配一个位置,经常运用于婚配单词边境 如:我想从字符串中”This is Regex”婚配零丁的单词 “is” 正则就要写成:
"This is Regex".match(/\bis\b/);
“b” 不会婚配is 双方的字符,但它会辨认is 双方是不是为单词的边境。“d”:婚配数字。
“w”:婚配字母,数字,下划线。等价于'[A-Za-z0-9_]’。
“s”:婚配空格。
“.”:婚配除了换行符之外的任何字符。
“[a-zA-Z]”:字符组 婚配包括括号内元素的字符。
几种反义:改成大写,意义就与本来的相反。
如:
“W”:婚配任何非单词字符。等价于’1‘。
“2“:婚配除了abc之外的恣意字符。字符转义:在正则表达式中元字符是有特别的寄义的,当我们要婚配元字符自身时,就需要用到字符转义,如:
/\./.test("."); // true
2.2 量词
2.2.1 经常运用量词
“*”(贪欲)反复零次或更多,贪欲量词会起首婚配全部字符串,尝试婚配时,它会选定尽量多的内容,假如 失利则回退一个字符,然后再次尝试回退的历程就叫做回溯,它会每次回退一个字符,直到找到婚配的内容或许没有字符能够回退。如:
"aaaaaa".match(/a*/) // ["aaaaaa"]
“?”(懒散)反复零次或一次,懒散量词运用另一种体式格局婚配,它从目的的肇端位置最早尝试婚配,每次搜检一个字符,并寻觅它要婚配的内容,云云轮回直到字符末端处。如:
"aaaaaa".match(/a?/) // ["a"]
“+”(占领)反复零次或更屡次,占领量词会掩盖事个目的字符串,然后尝试寻觅婚配内容 ,但它只尝试一次,不会回溯。如:
"aaaaaa".match(/a+/) // ["aaaaaa"]
“{n}” 反复n次;如:
"aaaaaa".match(/a{3}/) // ["aaa"]
“{n,m}” 反复n到m次;如:
"aaaaaa".match(/a{3,4}/) // ["aaaa"]
“{n,}” 反复n次或更屡次;如:
"aaaaaa".match(/a{3,}/) // ["aaaaaa"]
2.2.1 懒散限定符
“*?” 反复恣意次,但尽量少反复;如:
"aabab".match(/a.*?b/) // ["aab"]
为何第一个婚配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?简朴地说,由于正则表达式有另一条划定规矩,比懒散/贪欲划定规矩的优先级更高:最早最早的婚配具有最高的优先权。“+?” 反复1次或更屡次,但尽量少反复,与上面一样,只是最少要反复1次。如:
"aabab".match(/a.+?b/) // ["aab"]
“??” 反复0次或1次,但尽量少反复。如:
"aabab".match(/a.??b/) // ["aab"]
“{n,m}?” 反复n到m次,但尽量少反复。如:
"aaa".match(/a{1,3}?/) // ["a"]
“{n,}?” 反复n次以上,但尽量少反复。如:
"aaa".match(/a{1,}?/) // ["a"]
2.2.2 处置惩罚选项
javascript中正则表达式支撑的正则表达式有三个,g、i、m,离别代表全局婚配、疏忽大小写、多行形式。三种属性能够自由组合共存。
在默许的形式下,元字符 ^ 和 $ 离别婚配字符串的开首和末端处,形式 m 转变了这俩元字符的定义,让他们婚配一行的开首和末端。
三、正则进阶
3.1 捕捉分组
正则表达式一个最主要的特征就是将婚配胜利的形式的某部份举行存储供今后运用这一才能。对一个正则表达式形式或部份形式双方增加圆括号将致使这部份表达式存储到一个暂时缓冲区中。(能够运用非捕捉元字符 ‘?:’, ‘?=’, 或 ‘?!’ 来疏忽对这部份正则表达式的保留。)
所捕捉的每一个子婚配都按照在正则表达式形式中从左至右所碰到的内容存储。存储子婚配的缓冲区编号从 1 最早,一连编号直至最大 99 个子表达式。每一个缓冲区都能够运用 ‘n’ 接见,个中 n 为一个标识特定缓冲区的一名或两位十进制数。
后向援用一个最简朴,最有效的应用是供应了肯定笔墨中一连涌现两个雷同单词的位置的才能。举个例子:
/(\b[a-zA-Z]+\b)\s+\1\b/.exec(" asd sf hello hello asd"); //["hello hello", "hello"]
诠释这个例子:
1、(b[a-zA-Z]+b) 是一个捕捉分组,它捕捉一切的单词,
" asd sf hello hello asd".match(/(\b[a-zA-Z]+\b)/g) // ["asd", "sf", "hello", "hello", "asd"]
注:加上/g这个处置惩罚选项是便于我明白,没有这个选项的时刻,只输出第一个单词asd。
2、s加了一个空格限定前提,所以末了一个单词被消除,
" asd sf hello hello asd".match(/(\b[a-zA-Z]+\b)\s/g) \\ ["asd ", "sf ", "hello ", "hello "]
3、”1″后向援用,
" asd sf hello hello asd".match(/(\b[a-zA-Z]+\b)\s+\1\b/g) \\ ["hello hello"]
说实话,这个例子花了我很长时候去明白,有一点点想通,觉得这个观点看起来轻易,写起来并不轻易啊。
3.2 捕捉分组常有的用法(断言)
“(exp)” 婚配exp,并捕捉文本到自动定名的组里;如:
/(hello)\sworld/.exec("asdadasd hello world asdasd") // ["hello world", "hello"]
“(?:exp)” 婚配exp,不捕捉婚配的文本,也不给此分组分派组号;如:
/(?:hello)\sworld/.exec("asdadasd hello world asdasd") // ["hello world"]
“(?=exp)” 用来捕捉exp前面的字符,分组中的内容不会被捕捉,也不分派组号;如:
/hello\s(?=world)/.exec("asdadasd hello world asdasd") // ["hello "]
“(?!exp)” 捕捉背面不是exp的字符,一样不捕捉分组的内容,也不分派组号;如:
/hello\s(?!world)/.exec("asdadasd hello world asdasd") //null
world转变一下:
/hello\s(?!world)/.exec("asdadasd hello wosrlds asdasd") //["hello "]
“(?<!exp)” 婚配前面不是exp的位置;如:
/(?!<\d)123/.exec("abc123 ") // ["123"]
四、Javascript中正则表达式的运用
在JavaScript中定义一个正则表达式语法为:
var reg=/hello/ 或许 var reg=new RegExp("hello")
接着枚举一下JavaScript中能够运用正则表达式的函数,并简朴引见一下这些函数的作用。
4.1 String.prototype.search要领
用来找出原字符串中某个子字符串初次涌现的索引index,没有则返回-1。能够在官方文档中相识更多。
"abchello".search(/hello/); // 3
4.2 String.prototype.replace要领
用来替代字符串中的子串。简朴例子:
"abchello".replace(/hello/,"hi"); // "abchi"
在官方文档中有提到:
假如第一个参数是 RegExp对象,那末替代字符串能够插进去特别变量名$n,n是个小于100的非负整数,示意插进去第 n 个括号婚配的字符串。
所以我在文中一最早提到的需求就能够用 str.replace(/<span>(.*?)<\/span>/g, '<img src="$1"/>')
[$1示意/<span>(.?)</span>/g中的“(.?)”)婚配的字符串]
答案来解答。
4.3 String.prototype.split要领
用来支解字符串
"abchelloasdasdhelloasd".split(/hello/); //["abc", "asdasd", "asd"]
4.4 String.prototype.match要领
用来捕捉字符串中的子字符串到一个数组中。默许情况下只捕捉一个效果到数组中,正则表达式有”全局捕捉“的属性时(定义正则表达式的时刻增加参数g),会捕捉一切效果到数组中。
"abchelloasdasdhelloasd".match(/hello/); //["hello"]
"abchelloasdasdhelloasd".match(/hello/g); //["hello","hello"]
4.5 RegExp.prototype.exec要领
和字符串的match要领相似,这个要领也是从字符串中捕捉满足前提的字符串到数组中,然则也有两个区分。
1、exec要领一次只能捕捉一分子字符串到数组中,不管正则表达式是不是有全局属性
/hello/g.exec("abchelloasdasdhelloasd"); // ["hello"]
2、正则表达式对象(也就是JavaScript中的RegExp对象)有一个lastIndex属性,用来示意下一次从哪一个位置最早捕捉,每一次实行exec要领后,lastIndex就会今后推,直到找不到婚配的字符返回null,然后又从头最早捕捉。 这个属性能够用来遍历捕捉字符串中的子串。
var reg=/hello/g;
reg.lastIndex; //0
reg.exec("abchelloasdasdhelloasd"); // ["hello"]
reg.lastIndex; //8
reg.exec("abchelloasdasdhelloasd"); // ["hello"]
reg.lastIndex; //19
reg.exec("abchelloasdasdhelloasd"); // null
reg.lastIndex; //0
4.6 RegExp.prototype.test要领
用来测试字符串中是不是含有子字符串
/hello/.test("abchello"); // true
五、总结
总算是对正则表达式相识了一些,要熟练掌握还需背面多多实践^_^
参考资料:
1.http://www.cnblogs.com/zery/p…
2.http://www.cnblogs.com/tzyy/p…
3.http://www.codeyyy.com/regex/…