JavaScript正则表达式(一)

JavaScript正则表达式(一)

什么是正则表达式?

正则表达式(英文:Regular Expression)在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。

正则表达式中的特殊字符

正则表达式的直接量字符

\f

匹配换页符,等价于\x0c\cL

\n

匹配一个换行符,等价于\x0a\cJ

\r

匹配一个回车符,等价于\x0d\cM

\t

匹配一个制表符。等价于\x09\cI

\v

匹配一个垂直制表符。等价于\x0b\cK

\ /

 一个 / 直接量

\ \

一个 \ 直接量

\ .

一个 . 直接量

\ *

一个 * 直接量

\ +

一个 + 直接量

\ ?

一个 ? 直接量

\ |

一个 | 直接量

\ (

一个 ( 直接量

\ )

一个 ) 直接量

\ [

一个 [ 直接量

\ ]

一个 ] 直接量

\ {

一个 { 直接量

\ }

一个 } 直接量

\ XXX

由十进制数 XXX 指 定的ASCII码字符

\ Xnn

由十六进制数 nn 指定的ASCII码字符

\ cX

控制字符^X. 例如, \cI等价于 \t, \cJ等价于 \n

正则表达式的字符类

[...] 

字符集(characterset),匹配这个集合中的任一一个字符(或元字符)

[^...] 

不匹配这个集合中的任何一个字符。[^0-9]表示非数字,[^a-z]表示非小写字母

.

.’(小数点)会匹配字符串中除了换行符\n之外的所有字符,等价于[^\n]

\w

匹配一个可以组成单词的字符,包括字母、数字、下划线,等同于字符集合[a-zA-Z0-9_]。如[\w]匹配"$5.98"中的5,等于[a-zA-Z0-9]

\W

匹配一个不可以组成单词的字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9_]。无论是中文和“?”都算作是非单词字符

\s

匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]

\S

匹配任何非空白字符。等价于[^\f\n\r\t\v]

\d

匹配一个数字字符,/\d/=/[0-9]/

\D

匹配一个非数字字符,/\D/=/[^0-9]/

[\b]

匹配一个退格符

正则表达式的复制字符

{n}

精确匹配前一项n

{n,}

匹配前一项n次以上

{n,m}

匹配前一项n-m

?

匹配前一项0次或1,也就是说前一项是可选的. 等价于 {0, 1}

+

匹配前一项1次或多次,等价于{1,}

*

匹配前一项0次或多次.等价于{0,}

正则表达式的分组和选择

(...)

“分组”将几个项目分为一个单元.这个单元可由 *+、?和|等符号使用,而且还可以记住和这个组匹配的字符以供此后引用使用\n 和第n个分组所匹配的字符相匹配.分组是括号中的子表达式(可能是嵌套的).分组号是从左到右计数的左括号数

|

“选择”匹配该符号左边或者右边的子表达式

正则表达式的匹配位置

^

匹配的是字符的开头,在多行检索中,匹配的是一行的开头

^’在正则表达式开始部分的时候表示开头的意思,例如/^c/表示开头是c;但是在字符集和中,它表示的是类似“非”的意思

$

 匹配的是字符的结尾,在多行检索中,匹配的是一行的结尾

\b

匹配的是一个词语的边界,只有字符串的开头和结尾才算数。简而言之就是位于字符\w \w之间的位置(注意:[\b]匹配的是退格符)

\B

匹配的是非词语的边界的字符

正则表达式的修饰符

i

执行大小写不敏感的匹配

g

执行一个全局的匹配,简而言之,就是找到所有的匹配,而不是在找到第一个之后就停止了

m

修改^$在正则表达式中的作用,让它们分别表示行首和行尾

正则表达式的修饰特殊字符

\

(1)做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界。

(2)对正则表达式功能字符的还原,如"*"匹配它前面元字符0次或多次,/a*/将匹配a,aa,aaa,加了"\"后,/a\*/将只匹配"a*"

(pattern)

匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0$9属性。要匹配圆括号字符,请使用“\(”或“\)”。

(?:pattern)

匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。

(?=pattern)

正向预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

(?!pattern)

负向预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

\xn

匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.

\num

匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。

\n

标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。

\nm

标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若nm均为八进制数字(0-7),则\nm将匹配八进制转义值nm

\nml

如果n为八进制数字(0-3),且ml均为八进制数字(0-7),则匹配八进制转义值nml

\un

匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(?)。

 

创建一个正则表达式

第一种方法:

var reg = /pattern/;

第二种方法:

var reg = new  RegExp('pattern');

正则表达式的exec方法简介

语法:

reg.exec(str);

其中str为要执行正则表达式的目标字符串。

例如:

<script  type="text/javascript">

var reg = /test/;

var str = 'testString';

var result =  reg.exec(str);

alert(result);

</script>

将会输出test,因为正则表达式reg会匹配str(‘testString’)中的’test’子字符串,并且将其返回。

我们使用下面的函数来做匹配正则的练习:

function  execReg(reg,str){

 var result =  reg.exec(str);

 alert(result);

}

函数接受一个正则表达式参数reg和一个目标字符串参数str,执行之后会alert出正则表达式与字符串的匹配结果。

用这个函数测试上面的例子就是:

<script  type="text/javascript">

function  execReg(reg,str){

 var result =  reg.exec(str);

 alert(result);

}

var reg = /test/;

var str = 'testString';

execReg(reg,str);

</script>

上面的例子用正则里的test去匹配字符串里的test,实在是很无聊,同样的任务用indexOf方法就可以完成了。用正则,自然是要完成更强大的功能:

一片两片三四片,落尽正则全不见

上面的小标题翻译成正则就是{1},{2},{3,4},{1,}

c{n}

{1}表示一个的意思。

/c{1}/只能匹配一个c

/c{2}/则会匹配两个连续的c

以此类推,

/c{n}/则会匹配n个连续的c

看下面的例子:

reg = /c{1}/;

str='cainiao';

execReg(reg,str);

返回结果c

reg = /c{2}/;

str='cainiao';

execReg(reg,str);

返回结果null,表示没有匹配成功。

reg = /c{2}/;

str='ccVC果冻爽';

execReg(reg,str);

返回结果cc

c{m,n}

c{3,4}的意思是,连续的3c或者4c

例如

reg = /c{3,4}/;

str='ccVC果冻爽';

execReg(reg,str);

返回结果null,表示没有匹配成功。

reg = /c{3,4}/;

str='cccTest';

execReg(reg,str);

结果返回ccc

reg = /c{3,4}/;

str='ccccTest';

execReg(reg,str);

结果返回cccc,这表明正则会尽量多品牌,可34的时候它会选择多匹配一个。

reg = /c{3,4}/;

str='cccccTest';

execReg(reg,str);

仍然只匹配4c

由以上例子可以推断出,c{m,n}表示m个到nc,且m小于等于n

c{n,}

c{1,}表示1个以上的c。例如:

reg = /c{1,}/;

str='cainiao';

execReg(reg,str);

结果返回c

reg = /c{1,}/;

str='cccccTest';

execReg(reg,str);

返回ccccc,再次说明了正则表达式会尽量多地匹配。

reg = /c{2,}/;

str='cainiao';

execReg(reg,str);

结果返回nullc{2,}表示2个以上的c,而cainiao中只有1c

由以上例子可知,c{n,}表示最少nc,最多则不限个数。

*,+,?

*表示0次或者多次,等同于{0,},即

c* c{0,} 是一个意思。

+表示一次或者多次,等同于{1,},即

c+ c{1,} 是一个意思。

最后,?表示0次或者1次,等同于{0,1},即

c? c{0,1} 是一个意思。

贪心与非贪心

人都是贪婪的,正则也是如此。我们在例子reg = /c{3,4}/;str='ccccTest';的例子中已经看到了,能匹配四个的时候,正则绝对不会去匹配三个。上面所介绍的所有的正则都是这样,只要在合法的情况下,它们会尽量多去匹配字符,这就叫做贪心模式。

如果我们希望正则尽量少地匹配字符,那么就可以在表示数字的符号后面加上一个?。组成如下的形式:

{n,}?, *?, +?, ??, {m,n}?

同样来看一个例子:

reg = /c{1,}?/;

str='ccccc';

execReg(reg,str);

返回的结果只有1c,尽管有5c可以匹配,但是由于正则表达式是非贪心模式,所以只会匹配一个。

/^开头,结尾$/

^表示只匹配字符串的开头。看下面的例子:

reg = /^c/;

str='维生素c';

execReg(reg,str);

结果为null,因为字符串维生素c’的开头并不是c,所以匹配失败。

reg = /^c/;

str='cainiao';

execReg(reg,str);

这次则返回c,匹配成功,因为cainiao恰恰是以c开头的。

^相反,$则只匹配字符串结尾的字符,同样,看例子:

reg = /c$/;

str='cainiao';

execReg(reg,str);

返回null,表示正则表达式没能在字符串的结尾找到c这个字符。

reg = /c$/;

str='维生素c';

execReg(reg,str);

这次返回的结果是c,表明匹配成功。

’.’

‘.’会匹配字符串中除了换行符\n之外的所有字符,例如

reg = /./;

str='cainiao';

execReg(reg,str);

结果显示,正则匹配到了字符c

reg = /./;

str='blueidea';

execReg(reg,str);

这次是b

reg = /.+/;

str='blueidea——经典论坛  _';

execReg(reg,str);

结果是“blueidea——经典论坛 好_也就是说所有的字符都被匹配掉了,包括一个空格,一个下滑线,和一个破折号。

reg = /.+/;

reg = /.+/;

str='bbs.blueidea.com';

execReg(reg,str);

同样,直接返回整个字符串——bbs.blueidea.com,可见”.”也匹配”.”本身。

reg = /^./;

str='\ncainiao';

execReg(reg,str);

结果是null,终于失败了,正则要求字符串的第一个字符不是换行,但是恰恰字符是以\n开始的。

二选一,正则表达式中的或,“|“

b|c表示,匹配b或者c

例如:

reg = /b|c/;

str='blueidea';

execReg(reg,str);

结果是b

reg = /b|c/;

str='cainiao';

execReg(reg,str);

结果是c

reg = /^b|c.+/;

str='cainiao';

execReg(reg,str);

匹配掉整个cainiao

reg = /^b|c.+/;

str='bbs.blueidea.com';

execReg(reg,str);

结果只有一个b,而不是整个字符串。因为上面正则表达式的意思是,匹配开头的b或者是c.+

括号()

reg = /^(b|c).+/;

str='bbs.blueidea.com';

execReg(reg,str);

这次的结果是整个串bbs.blueidea.com,机上上面的括号这后,这个正则的意思是,如果字符串的开头是b或者c,那么匹配开头的b或者c以及其后的所有的非换行字符。

如果你也实验了的话,会发现返回的结果后面多出来一个“,b“,这是()内的b|c所匹配的内容。我们在正则表达式内括号里写的内容会被认为是子正则表达式,所匹配的结果也会被记录下来供后面使用。我们暂且不去理会这个特性。

字符集合[abc]

[abc]表示a或者b或者c中的任意一个字符。例如:

reg = /^[abc]/;

str='bbs.blueidea.com';

execReg(reg,str);

返回结果是b

reg = /^[abc]/;

str='test';

execReg(reg,str);

这次的结果就是null了。

我们在字字符集合中使用如下的表示方式:[a-z],[A-Z],[0-9],分别表示小写字母,大写字母,数字。例如:

reg =  /^[a-zA-Z][a-zA-Z0-9_]+/;

str='test';

execReg(reg,str);

结果是整个test,正则的意思是开头必须是英文字母,后面可以是英文字母或者数字以及下划线。

反字符集合[^abc]

^在正则表达式开始部分的时候表示开头的意思,例如/^c/表示开头是c;但是在字符集和中,它表示的是类似的意思,例如[^abc]就表示不能是ab或者c中的任何一个。例如:

reg = /[^abc]/;

str='blueidea';

execReg(reg,str);

返回的结果是l,因为它是第一个非abc的字符(即第一个b没有匹配)。同样:

reg = /[^abc]/;

str='cainiao';

execReg(reg,str);

则返回i,前两个字符都是[abc]集合中的。

由此我们可知:[^0-9]表示非数字,[^a-z]表示非小写字母,一次类推。

边界与非边界 \b \B

\b表示的边界的意思,也就是说,只有字符串的开头和结尾才算数。例如/\bc/就表示字符串开始的c或者是结尾的c。看下面的例子:

reg = /\bc/;

str='cainiao';

execReg(reg,str);

返回结果c。匹配到了左边界的c字符。

reg = /\bc/;

str='维生素c';

execReg(reg,str);

仍然返回c,不过这次返回的是右侧边界的c

reg = /\bc/;

str='bcb';

execReg(reg,str);

这次匹配失败,因为bcb字符串中的c被夹在中间,既不在左边界也不再右边界。

\b对应\B表示非边界。例如:

reg = /\Bc/;

str='bcb';

execReg(reg,str);

这次会成功地匹配到bcb中的c,。然而

reg = /\Bc/;

str='cainiao';

execReg(reg,str);

则会返回null。因为\B告诉正则,只匹配非边界的c

数字与非数字 \d \D

\d表示数字的意思,相反,\D表示非数字。例如:

reg = /\d/;

str='cainiao8';

execReg(reg,str);

返回的匹配结果为8,因为它是第一个数字字符。

reg = /\D/;

str='cainiao8';

execReg(reg,str);

返回c,第一个非数字字符。

空白\f \n \r \t \v \s \S

\f匹配换页符,\n匹配换行符,\r匹配回车,\t匹配制表符,\v匹配垂直制表符。

\s匹配单个空格,等同于[\f\n\r\t\v]。例如:

reg = /\s.+/;

str='This is a test  String.';

execReg(reg,str);

返回“is a test String.”,正则的意思是匹配第一个空格以及其后的所有非换行字符。

同样,\S表示非空格字符。

reg = /\S+/;

str='This is a test  String.';

execReg(reg,str);

匹配结果为This,当遇到第一个空格之后,正则就停止匹配了。

单词字符 \w \W

\w表示单词字符,等同于字符集合[a-zA-Z0-9_]。例如:

reg = /\w+/;

str='blueidea';

execReg(reg,str);

返回完整的blueidea字符串,因为所有字符都是单词字符。

reg = /\w+/;

str='.className';

execReg(reg,str);

结果显示匹配了字符串中的className,只有第一个“.”——唯一的非单词字符没有匹配。

reg = /\w+/;

str='中文如何?';

execReg(reg,str);

试图用单词字符去匹配中文自然行不通了,返回null

\W表示非单词字符,等效于[^a-zA-Z0-9_]

reg = /\W+/;

str='中文如何?';

execReg(reg,str);

返回完整的字符串,因为,无论是中文和都算作是非单词字符。

反向引用 /(子正则表达式)\1/

形式如下:/(子正则表达式)\1/

依旧用例子来说明:

1.

reg = /\w/;

str='blueidea';

execReg(reg,str);

返回b

2.

reg = /(\w)(\w)/;

str='blueidea';

execReg(reg,str);

返回bl,b,l

bl是整个正则匹配的内容,b是第一个括号里的子正则表达式匹配的内容,l是第二个括号匹配的内容。

3.

reg = /(\w)\1/;

str='blueidea';

execReg(reg,str);

则会返回null。这里的“\1”就叫做反向引用,它表示的是第一个括号内的字正则表达式匹配的内容。在上面的例子中,第一个括号里的(\w)匹配了b,因此“\1”就同样表示b了,在余下的字符串里自然找不到b了。

与第二个例子对比就可以发现,“\1”是等同于1个括号匹配的内容,而不是第一个括号的内容

reg = /(\w)\1/;

str='bbs.blueidea.com';

execReg(reg,str);

这个正则则会匹配到bb

同样,前面有几个子正则表达式我们就可以使用几个反向引用。例如:

reg = /(\w)(\w)\2\1/;

str='woow';

execReg(reg,str);

会匹配成功,因为第一个括号匹配到w,第二个括号匹配到o,而\2\1则表示ow,恰好匹配了字符串的最后两个字符。

括号(2

前面我们曾经讨论过一次括号的问题,见下面这个例子:

reg = /^(b|c).+/;

str='bbs.blueidea.com';

execReg(reg,str);

这个正则是为了实现只匹配以b或者c开头的字符串,一直匹配到换行字符,但是。上面我们已经看到了,可以使用“\1”来反向引用这个括号里的子正则表达式所匹配的内容。而且exec方法也会将这个字正则表达式的匹配结果保存到返回的结果中。

不记录子正则表达式的匹配结果 (?:pattern)

使用形如(?:pattern)的正则就可以避免保存括号内的匹配结果。例如:

reg = /^(?:b|c).+/;

str='bbs.blueidea.com';

execReg(reg,str);

可以看到返回的结果不再包括那个括号内的字正则表达式多匹配的内容。

同理,反向引用也不好使了:

reg = /^(b|c)\1/;

str='bbs.blueidea.com';

execReg(reg,str);

返回bb,bbb是整个正则表达式匹配的内容,而b是第一个子正则表达式匹配的内容。

reg = /^(?:b|c)\1/;

str='bbs.blueidea.com';

execReg(reg,str);

返回null。由于根本就没有记录括号内匹配的内容,自然没有办法反向引用了。

正向预查 (?=pattern)

形式:(?=pattern)

所谓正向预查,意思就是:要匹配的字符串,后面必须紧跟着pattern

我们知道正则表达式/cainiao/会匹配cainiao。同样,也会匹配cainiao9中的cainiao。但是我们可能希望,cainiao只能匹配cainiao8中的菜鸟。这时候就可以像下面这样写:/cainiao(?=8)/,看两个实例:

reg = /cainiao(?=8)/;

str='cainiao9';

execReg(reg,str);

返回null

reg = /cainiao(?=8)/;

str='cainiao8';

execReg(reg,str);

匹配cainiao

需要注意的是,括号里的内容并不参与真正的匹配,只是检查一下后面的字符是否符合要求而已,例如上面的正则,返回的是cainiao,而不是cainiao8

再来看两个例子:

reg = /blue(?=idea)/;

str='blueidea';

execReg(reg,str);

匹配到blue,而不是blueidea

reg = /blue(?=idea)/;

str='bluetooth';

execReg(reg,str);

返回null,因为blue后面不是idea

reg = /blue(?=idea)/;

str='bluetoothidea';

execReg(reg,str);

同样返回null

?!

形式(?!pattern)?=恰好相反,要求字符串的后面不能紧跟着某个pattern,还拿上面的例子:

reg = /blue(?!idea)/;

str='blueidea';

execReg(reg,str);

返回null,因为正则要求,blue的后面不能是idea

reg = /blue(?!idea)/;

str='bluetooth';

execReg(reg,str);

则成功返回blue

匹配元字符 \

首先要搞清楚什么是元字符呢?我们之前用过*,+,?之类的符号,它们在正则表达式中都有一定的特殊含义,类似这些有特殊功能的字符都叫做元字符。例如

reg = /c*/;

表示有任意个c,但是如果我们真的想匹配’c*’这个字符串的时候怎么办呢?只要将*转义了就可以了,如下:

reg = /c\*/;

str='c*';

execReg(reg,str);

返回匹配的字符串:c*

同理,要匹配其他元字符,只要在前面加上一个“\”就可以了。

正则表达式的修饰符

全局匹配,修饰符g

形式:/pattern/g

例子:reg = /b/g;

后面再说这个g的作用。先看后面的两个修饰符。

不区分大小写,修饰符i

形式:/pattern/i

例子:

var reg = /b/;

var str = 'BBS';

execReg(reg,str);

返回null,因为大小写不符合。

var reg = /b/i;

var str = 'BBS';

execReg(reg,str);

匹配到B,这个就是i修饰符的作用了。

行首行尾,修饰符m

形式:/pattern/m

m修饰符的作用是修改^$在正则表达式中的作用,让它们分别表示行首和行尾。例如:

var reg = /^b/;

var str = 'test\nbbs';

execReg(reg,str);

匹配失败,因为字符串的开头没有b字符。但是加上m修饰符之后:

var reg = /^b/m;

var str = 'test\nbbs';

execReg(reg,str);

匹配到b,因为加了m修饰符之后,^已经表示行首,由于bbs在字符串第二行的行首,所以可以成功地匹配。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值