正则表达式
对于正则表达式可是又爱又恨,爱的是正则表达式在编程中实用作用大,恨的是学了太容易忘记,因此将正则表达式的语法记录下来,加深记忆,又方便查阅。
正则表达式(Regular Expression,简写:RegExp)可以用来匹配或替换某些模式的字符,而正则表达式则是这些模式。
当写的正则表达式不确定是否正确时,可以使用测试工具测试:在线表达式测试。当不太确定正则表达式的意思时,可以使用分析工具分析:正则分析器。
创建RegExp
创建正则表达式的方法有两种:
1. 直接量语法
直接通过斜杠/
包住元字符即可声明一个正则表达式:
var reg = /hello/ |
2. 创建RegExp对象的语法
通过RegExp实例化:
var reg = new RegExp('hello' , 'g') |
RegExp第一个参数为正则表达式,第二个参数可选,修饰符。下面将会有详解介绍。
语法
正则表达式由一些普通的字符和元字符组成。普通的字符比如匹配hello这个字符,那么正则表达式可以写为/hello/。而元字符有多种,可以根据元字符的用法分为几类:基本元字符、定义类元字符、数量类元字符、位置类元字符、修饰符类字符。
基本元字符:
基本元字符划分较基本的元字符:
.
: 匹配除换行符\n
之外的任何字符。如/./
,可以匹配a
、A
或_
等非换行符字符。\
: 与下一个字符搭配,匹配为一个特殊字符。如/n/
,匹配的是一个n
字符,如果正则表达式为/\n/
,则匹配一个换行符。|
: 逻辑或操作符。
var reg = /hello|world/g, |
[ ]
: 匹配字符的合集,可匹配集合中的任何一个字符。在[ ]
中.
、*
、\
等表示其本身。
var reg = /1[234]2/g, |
[^]
: 表示非,对集合里面的字符取非。如[^.*]
,可以匹配不为.
或*
的字符。-
: 在[]
中使用,定义一个区间。如/[a-z]/
,可以匹配a到z的小写字母。()
: 表示分组。
//可以用来匹配hello xxx也可以用来匹配helloworld |
()
还可以用来表示捕获括号,捕获括号里的表达式叫做子表达式,捕获的子串可以通过RegExp的属性$1、$2...$9
获得。
var reg = /(\d+)-(\d+)-(\d+)/, |
如果不想捕获,只想使用分组的功能,可以使用(?:p)
表示不捕获。
var reg = /(\d+)-(?:\d+)-\d+/, |
定义类元字符:
定义类元字符表示用某些字符表示一类字符:
\d
: 匹配一个数字字符,等价于/[0-9]/
。digit的缩写。\D
: 匹配一个非数字的字符,等价于/[^0-9]/
。\w
: 匹配一个大小写字母数字下划线的字符,等价于/[a-zA-Z0-9_]/
。word的缩写。\W
: 匹配一个非大小写字母数字下划线的字符,等价于/[^a-zA-Z0-9_]/
。\s
: 匹配一个空白符,包括空格、换行符(\n
)、回车符(\r
)、水平制表符(\t
)、垂直制表符(\v
)、换页符(\f
),等价于/[\n\r\t\v\f]/
。space的缩写。\S
: 表示一个非空白符。等价于/[^\n\r\t\v\f]/
。
数量类元字符:
数量类元字符表示前面的字符匹配的数量:
{m}
: 表示前面的字符重复m次。如/\d{2}/
,匹配两个数字,如可以匹配12。{m,n}
: 表示前面的字符至少重复m次,至多重复n次。如/\d{2,4}/
,123和32都可以匹配得到。另外,{m,}表示至少m次。?
: 表示前面的字符出现0次或1次。等价于{0,1}。还有一种情况,默认情况下,正则的匹配是贪婪模式,?
如果跟在量词*
、{}
、?
、+
后面,就会使得匹配变成非贪婪模式。下面将会介绍贪婪模式和非贪婪模式。
//贪婪模式: 尽可能的匹配更多的字符 |
+
: 表示前面的字符至少出现一次。等价于{1,}。*
: 表示前面的字符出现零次或多次。等价于{0,}。
位置类元字符:
位置类元字符匹配的是位置,而非前面所说的字符。如字符串abc
,这个字符共有4个位置:(位置)a(位置)b(位置)c(位置)。
^
: 匹配的是表达式的开始位置。$
: 匹配的是表达式的结束位置。
//在abc的开始位置和结束位置插入`*` |
(?=p)
: 匹配的是p
前面的位置。如在字符aa
前插入bb
:
var str = 'baac'.replace(/(?=aa)/,'bb'); |
(?!0)
: 匹配的不是p
前面的位置。如在非字符aa
前插入dd
:
var str = 'baac'.replace(/(?!aa)/,'dd'); |
\b
: 匹配单词的边界。单词边界指的是\w([a-zA-Z0-9_])
和\W
之前的边界,包括\w
和^
以及$
之间的位置。
//在单词边界插入* |
\B
: 匹配非单词的边界。
修饰符类字符:
g
: 全局匹配
//用*代替ab,reg1为全局搜索,reg2未设全局搜索 |
i
: 不区分大小写匹配
//查询字符串中是否包含a |
m
: 多行搜索
方法
对于正则来说,可以有两种类型的调用方法进行:一个是正则对象上的方法,一个是string对象上的方法。
正则对象上的方法
正则对象上的方法有test
、exec
:
1.test方法
用于检测一个字符串是否匹配某个模式。
RegExpObject.test(string) |
参数为一个字符串。如果匹配返回true,不匹配返回false。
var reg = /abc/, |
2.exec方法
用来检索字符串中的正则表达式的匹配。
RegExpObject.exec(string) |
参数为一个字符串。当匹配时,返回一个数组。否则返回null。
返回的数组中,第0个元素为匹配的字符,第1个元素(如果有子表达式的话)为RegExpObject的第1个字表达式相匹配的的字符,第2个元素(如果有的话)为RegExpObject的第2个字表达式相匹配的的字符,以此类推。除此之外返回的数组还包含两个属性index
和input
,index
为第0个元素匹配字符的第一个字符的位置,input
为被检索的原字符string。
var reg = /([a-z])[a-z]{1,3}/; |
还有另外一种情况,当RegExpObject为全局检索时,第一次检索时匹配的开始位置为0,即RegExpObject的属性lastIndex为0,第二次检索会从第一次匹配成功的字符的下一个位置开始检索,此时lastIndex为下一个位置,第三次检索会从第二次匹配成功的字符的下一个位置开始检索,以此类推,直到最后没有匹配返回null。
var reg = /([a-z])[a-z]{1,3}/, |
因此可以在循环中反复调用exec获得全部的匹配信息:
var reg2 = /([a-z])[a-z]{1,3}/g; |
string对象上的方法
string对象上支持正则的方法有:search、match、replace、split
1.search
用于检索字符串中与正则表达式匹配的字符的位置。
stringObject.search(regexp) |
如果找到匹配的字符串则返回匹配的第一个字符的位置,否则,返回-1。
var reg = /\d/, |
2.match
用于检索字符串中匹配的字符。
stringObject.match(regexp) |
如果检索到匹配的字符,则返回一个数组,否则,返回null。
当regexp不是全局匹配时,match方法返回的数组和exec方法没用全局匹配返回的数组相同。第0个元素为匹配的字符,第1个元素(如果有子表达式的话)为RegExpObject的第1个字表达式相匹配的的字符,以此类推。还有index
和input
属性。
当regexp是搜索时,match方法返回的包含所有匹配的字符的数据。
var reg = /([a-z])[a-z]{1,3}/, |
3.replace
用于替换正则表达式匹配的字符。
stringObject.replace(regexp,string/function) |
第一个参数为正则表达式,第二个参数为替换文本或函数,返回的是替换之后的新字符串。
如果regexp是全局检索的,那么replace方法将会替换所有匹配的子串。否则,它只替换第一个匹配的子串。
var reg = /xxx/, |
第二个参数中可以使用具有特殊意义的$
符号匹配:
$1、$2、...
: 与regexp中第1、第2子表达式相匹配的文本$&
: 与regexp相匹配的子串$`
: 位于匹配字串左侧的文本$'
: 位于匹配字串右侧的文本$$
: 直接量符号
var reg = /(\w+) (\w+)/, |
如果第二个参数是函数的话,函数的入参如下:
match
: 与regexp相匹配的子串,同上$&
p1,p2...
: 与regexp中第1、第2子表达式相匹配的文本,同上$1、$2、...
offset
: 匹配到子串第一个字符的位置 string
: 被匹配的原字符串
var reg = /(\w+) (\w+)/, |
4.split
根据正则表达式匹配的子串分割成数组。
stringObject.split(regexp , howmany); |
第一个参数为正则表达式,第二个参数为指定返回数组的最大长度。split方法返回的是一个数组。
返回的数组中是不包含匹配的子串,如果想要包含匹配的子串,需要给正则加上捕获括号。
var reg = /\,/, |
匹配特殊用法
反向引用
将捕获括号内匹配的内容保存到一个以数字编号的组里,再使用该数字编号,则是反向引用。
比如想要匹配日期,正则表达式为/(\d+)[./-](\d+)[./-](\d+)/
,可以匹配日期格式1980.09.07、1980/09/07、1980-09-07,那么可以匹配为1980/09.07,不是我们想要的结果,我们想要的日期分隔符能够统一,那么可以使用反向引用实现。
var reg = /(\d+)([./-])(\d+)\2(\d+)/; |
反向引用的数字编号\n
中n
为第n个捕获括号。