前期学习Java时,了解了正则表达式,没有深刻了解之后通过视频相关的学习写了一些代码,时隔几月,重新想再把它回顾一遍,今后应该会再次遇到,记下来以便参考。
简介:
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
正则表达式是烦琐的,但它是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。
第一步:(初级)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo</title>
</head>
<body>
<script>
var str = "abc123def";
var patt1 = /[0-9]+/;
document.write(str.match(patt1));
</script>
</body>
</html>
特殊字符 、 限定字符
特殊字符 | 描述 |
---|---|
$ | 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。 |
() | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。 |
* | 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。 |
+ | 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。 |
. | 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。 |
[ | 标记一个中括号表达式的开始。要匹配 [,请使用 \[。 |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。 |
\ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。 |
^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。 |
{ | 标记限定符表达式的开始。要匹配 {,请使用 \{。 |
| | 指明两项之间的一个选择。要匹配 |,请使用 \|。 |
限定字符 | 描述 |
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 |
下面看看元字符吧!
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":匹配任何非单词字符。等价于'[^A-Za-z0-9_]'。
"[^abc]":匹配除了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 改变了这俩元字符的定义,让他们匹配一行的开头和结尾。
(一) 捕获分组
正则表达式一个最重要的特性就是将匹配成功的模式的某部分进行存储供以后使用这一能力。对一个正则表达式模式或部分模式两边添加圆括号将导致这部分表达式存储到一个临时缓冲区中。(可以使用非捕获元字符 '?:', '?=', 或 '?!' 来忽略对这部分正则表达式的保存。)
所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
后向引用一个最简单,最有用的应用是提供了确定文字中连续出现两个相同单词的位置的能力。
举个例子:
/(\b[a-zA-Z]+\b)\s+\1\b/.exec(" asd sf heString.prototype.match方法llo 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"]
很长的代码。 不仔细写很容易出错,要理解到其中的意思。
(二)捕获分组常有的用法(断言)
- "(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中可以使用正则表达式的函数,并简单介绍一下这些函数的作用。
1、String.prototype.search方法
用来找出原字符串中某个子字符串首次出现的索引index,没有则返回-1。可以在官方文档中了解更多。
"abchello".search(/hello/); // 3
2、String.prototype.replace方法
用来替换字符串中的子串。简单例子:
"abchello".replace(/hello/,"hi"); // "abchi"
在官方文档中有提到:
如果第一个参数是 RegExp对象,那么替换字符串可以插入特殊变量名$n,n是个小于100的非负整数,表示插入第 n 个括号匹配的字符串。
所以我在文中一开始提到的需求就可以用
str.replace(/<span>(.*?)<\/span>/g, '<img src="$1"/>')
[$1表示/(.?)</span>/g中的“(.?)”)匹配的字符串]
答案来解答。
用来分割字符串
"abchelloasdasdhelloasd".split(/hello/); //["abc", "asdasd", "asd"]
4、String.prototype.match方法
用来捕获字符串中的子字符串到一个数组中。默认情况下只捕获一个结果到数组中,正则表达式有”全局捕获“的属性时(定义正则表达式的时候添加参数g),会捕获所有结果到数组中。
"abchelloasdasdhelloasd".match(/hello/); //["hello"]
"abchelloasdasdhelloasd".match(/hello/g); //["hello","hello"]
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
6、RegExp.prototype.test方法
用来测试字符串中是否含有子字符串
/hello/.test("abchello"); // true
参考资料:
1.http://www.cnblogs.com/zery/p/3438845.html
2.http://www.cnblogs.com/tzyy/p/4927476.html
3.http://www.codeyyy.com/regex/index.html
正则举例参考:http://www.cnblogs.com/wj204/p/6576681.html