频道栏目
首页 > 资讯 > JavaScript > 正文

JavaScript基础——引用类型(二)日期类型Date、正则表达式类型RegExp

16-05-28        来源:[db:作者]  
收藏   我要投稿

Date类型

ECMAScript中的Date类型是在早期Java中的java.util.Date类基础上构建的。为此,Date类型使用自UTC(CoordinatedUniversal Time,国际协调时间)1970年1月1日午夜(零时)开始经过的毫秒数来保存日期。在使用这种数据存储格式的条件下,Date类型保存的日期能够精确到1970年1月1日之前或之后的285 616年。

要创建一个日期对象,使用new 操作符和Date构造函数即可,如:

var now = new Date();

在调用Date构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间。如果想根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数(即从1970年1月1日午夜起至该日期经过的毫秒数)。为了简化这一计算过程,ECMAScript提供了两个方法:Date.parse()和Date.UTC()。

其中Date.parse()方法接收一个表示日期的自复查un参数,然后尝试根据这个字符串返回相应日期的毫秒数。ECMA-262没有定义Date.parse()应该支持哪种日期格式,因此这个方法的行为因实现而异,而且通常是因地区而异。

如果传入Date.parse()方法的字符串不能表示日期,那么它会返回NaN。实际上,如果直接将表示日期的字符串传递给Date构造函数,也会在后台调用Date.parse()。换句话说,下面的两句代码是等价的:

var date = new Date(Date.parse(“May 25 ,2016”));

var date = new Date( “May 25 , 2016”);

Date.UTC()方法同样也返回表示日期的毫秒数,但它与Date.parse()在构建时使用不同的信息。Date.UTC()的参数分别是年份、基于0的月份(一月是0,二月是1,以此类推)、月中的哪一天(1到31)、小时数(0到23)、分钟、秒以及毫秒数。在这些参数中,只有前两个参数(年和月)是必需的。如果没有提供月中的天数,则假设天数为1;如果省略其他参数,则统统假设为0。以下是使用Date.UTC()方法的例子:

//GMT 时间2000年1月1日午夜零时

var y2k = new Date(Date.UTC(2000 , 0));

//GMT时间2005年5月5日下午5:55:55

var allFives = new Date(Date.UTC(2005 , 4 ,5 , 17 , 55 , 55));

这个例子创建了两个日期对象。第一个对象表示GMT时间2000年1月1日午夜零时,传入的值一个是表示年份的2000,一个是表示月份的0(即一月)。因为其他参数是自动填充的(即月中的天数为1,其他所有参数均为0),所以结果就是该月第一天的午夜零时。第二个对象表示GMT时间2005年5月5日下午5:55:55,即使日期和时间中只包含5,也需要传入不一样的参数:月份必须是4(因为月份是基于0的)、小时必须设置为17(因为小时以0到23表示),剩下的参数就很直观了。

如同模仿Date.parse()一样,Date构造函数也会模仿Date.UTC(),但有一点明显不同:日期和时间都基于本地时区而非GMT来创建。不过,Date构造函数接收的参数仍然与Date.UTC()相同。因此,如果第一个参数是数值,Date构造函数就会假设该值是日期中的年份,而第二个参数是月份,一次类推。据此,可以将前面的例子重写如下:

//本地时间2000年1月1日午夜零时

var y2k = new Date(2000 , 0);

//本地时间2005年5月5日下午5:55:55

var allFives = new Date(2005 , 4 , 5 , 17 ,55 , 55);

以上代码创建了与前面例子中相同的两个日期对象,只不过这次的日期都是基于系统设置的本地时区创建的。

ECMAScript5添加了Date.now()方法,返回表示调用这个方法时的日期和时间的毫秒数。这个方法简化了使用Date对象分析代码的工作。例如:

//取得开始时间

var start = Date.now();

//执行某些操作

……

//取得停止时间

var stop = Date.now();

var result = stop – start;

支持Date.now()方法的浏览器包括IE9+、Firefox3+、Safari3+、Opera10.5和Chrome。在不支持它的浏览器中,使用+操作符把Date对象转换成字符串,也可以达到同样的目的。

/取得开始时间

var start =+new Date ();

//执行某些操作

……

//取得停止时间

var stop = +new Date ();

var result = stop – start;

继承的方法

与其他引用类型一样,Date类型也重写了toLocalString()、toString()和valueOf()方法;但这些方法返回的值与其他类型中的方法不同。Date类型的toLocalString()方法会按照与浏览器设置的地区相适应的格式返回日期和时间。这大致意味着时间格式中会包含AM或PM,但不会包含时区信息(当然,具体的格式会因浏览器而异)。而toString()方法则通常返回带有时区信息的日期和时间,其中时间一般以军用时间(即小时的范围是0到23)表示。下面给出了在不同浏览器中调用toLocalString()和toString()方法,输出PST(Pacific Standard Time,太平洋标准时间)时间2016年5月25日午夜零时的结果。

IE11:

toLocalString()——?2016?年?5?月?25?日??00?:?00?:?00

toString()——Wed May 25 201600:00:00 GMT+0800 (中国标准时间)

Firefox4:

toLocalString()——2016/5/25 上午12:00:00

toString()——Wed May 25 201600:00:00 GMT+0800

Chrome4:

toLocalString()——2016/5/25 上午12:00:00

toString()——Wed May 25 201600:00:00 GMT+0800 (中国标准时间)

这两个方法在不同的浏览器中返回的日期和时间格式大相径庭。事实上toLocalString()和toString()的这一差别仅在调试代码时比较有用,而在显示日期和时间时没有什么价值。

至于Date类型的valueOf()方法,则根本不返回字符串,而是返回日期的毫秒表示。因此,可以方便使用比较操作符来比较日期值。如:

var date1 = new Date(2007,0,1);

var date2 = new Date(2007,1,1);

alert(date1 < date2);//true

alert(date1 > date2);//false

日期格式化方法

Date类型还有一些专门用于将日期格式化为字符串的方法,这些方法如下。

(1)toDateString():以特定于实现的格式显示星期几、月、日和年;

(2)toTimeString():以特定于实现的格式显示时、分、秒和时区;

(3)toLocaleDateString():以特定于地区的格式显示星期几、月、日和年;、

(4)toLocaleTimeString():以特定于实现的格式显示时、分、秒;

(5)toUTCString():以特定于实现的格式完整的UTC日期。

与toLocaleSTring()和toString()方法一样,以上这些字符串格式方法的输出也是因浏览器而异的,因此没有哪一个方法能够用来在用户页面中显示一致的日期信息。

除了前面介绍的方法之外,还有一个toGMTString()的方法,这是一个与toUTCSTring()等价的方法,其存在目的在于确保向后兼容。不过,ECMAScript推荐现在编写的代码一律使用toUTCString()方法。

日期/时间组件方法

直接取得和设置日期值的方法

方法

说明

getTime()

返回表示日期的毫秒数;与valueOf()方法返回的值相同

setTime(毫秒)

以毫秒数设置日期,会改变整个日期

getFullYear()

取得4位数的年份(如2016而非仅16)

getUTCFullYear()

返回UTC日期的4位数年份

setFullYear(年)

设置日期的年份。传入的年份值必须是4位数字

setUTCFullYear(年)

设置UTC日期的年份。传入的年份值必须是4位数字

getMonth()

返回日期中的月份,其中0表示一月,11表示十二月

getUTCMonth()

返回UTC日期中的月份,其中0表示一月,11表示十二月

setMonth(月)

设置日期中的月份。传入的月份值必须大于0,超过11则增加年份

setUTCMonth(月)

设置UTC日期中的月份。传入的月份必须大于0,超过11则增加年份

getDate()

返回日期月份中的天数(1到31)

getUTCDate()

返回UTC日期月份中的天数(1到31)

setDate(日)

设置日期月份中的天数。如果传入的值超过了该月中应有的天数,则增加月份

setUTCDate(日)

设置UTC日期月份中的天数。如果传入的值超过了该月中应有的天数,则增加月份

getDay()

返回日期中星期的星期几(其中0表示星期日,6表示星期六)

getUTCDay()

返回UTC日期中星期的星期几(其中0表示星期日,6表示星期六)

getHours()

返回日期中的小时数(0到23)

getUTCHours()

返回UTC日期中的小时数(0到23)

setHours(时)

设置日期中的小时数,传入的值超过了23则增加月份中的天数。传入的值为负数,则实际值为前一天的24减参数的绝对值小时。

setUTCHours(时)

设置UTC日期中的小时数,传入的值超过了23则增加月份中的天数。传入的值为负数,则实际值为前一天的24减参数的绝对值小时。

getMinutes()

返回日期中的分钟数(0到59)。

getUTCMinutes()

返回UTC日期中的分钟数(0到59)。

setMibutes(分)

设置日期中的分钟数,传入的值超过59则增加小时数

setUTCMinutes(分)

设置UTC日期中的分钟数,传入的值超过59则增加小时数

getSeconds()

返回日期中的秒数(0到59)

getUTCSeconds()

返回UTC日期中的秒数(0到59)

setSeconds(秒)

设置日期中的秒数,传入的值超过59则增加分钟数

setUTCSeconds(秒)

设置UTC日期中的秒数,传入的值超过59则增加分钟数

getMilliseconds()

返回日期中的毫秒数

getUTCMilliseconds()

返回UTC日期中的毫秒数

setMilliseconds(毫秒)

设置日期中的毫秒数

setUTCMilliseconds(毫秒)

设置UTC日期中的毫秒数

getTimezoneOffset()

返回本地时间与UTC时间相差的分钟数。

使用上面的方法进行一系列的操作后会发现一些有趣的地方,直接打开浏览器调试,在控制台进行测试即可:

Chrome4:

var date = new Date();

date.setTime(0);

console.log(date.toLocaleString());//1970/1/1 上午8:00:00

var millisecondesOfaDay = 86400000;

date.setTime(-millisecondesOfaDay);

console.log(date.toLocaleString());//1969/12/31上午8:00:00

date.setMonth(24);

console.log(date.toLocaleString());//1971/1/31 上午8:00:00

date.setMonth(-24);

console.log(date.toLocaleString());//1969/1/31 上午8:00:00

上面的代码中第一行创建了一个date对象,第二行设置date与1970年1月1日 00:00:00的毫秒偏差为0。按道理在第三行输出时间应该为1970/1/1 上午0:00:00才对,八个小时是怎么多出来的呢?

其实这么输出信息是有迷惑性的,调用toString()方法后就很明朗了:

var date = new Date();

date.setTime(0);

console.log(date.toString());//Thu Jan 01 197008:00:00 GMT+0800 (中国标准时间)

这样,带上时区后,多出的八个小时就得到解释了。

继续往下看,可以看到所有的setXXX()方法不仅可以接收正数,还能接收负数,而这里的正负就是正反的标识,如果是正数就向前(未来)数时间,如果是负数就向后(过去)数时间,比如,setDate(1)表示的是该月的第一天,而setDate(0)表示的就是上个月的最后一天。

var date1 = new Date(2016 , 2 , 1);

date1.setDate(0);

console.log(date1.toLocaleString());//2016/2/29上午12:00:00

var date2 = new Date(2016 , 2 , 1);

date2setDate(1);

console.log(date2.toLocaleString());//2016/3/1上午12:00:00

从上面所有的例子可以看出在JavaScript中的时间各项(年、月、日、时、分、秒及毫秒)之间是相互影响的——会向高位溢出。

还有一点是Date中没有setDay()及setUTCDay()方法,这两个属性是只读的,是后台自动计算得出的。

日期计算

Date类中没有提供相关的日期计算方法,其实其已经给出了方便的日期计算方法,就是使用getXXX()与setXXX()方法:

var date = new Date(2016 , 4 , 26 , 15 , 08, 0);

console.log(date.toLocaleString());

date.setDate(date.getDate()-27);//2016/5/26 下午3:08:00

//27天前的日期

console.log(date.toLocaleString());//2016/4/29下午3:08:00

可以通过简单的封装就可以指定一套自己的日期计算方法,如:

function toCharacterString(date){

var localeString = date.toLocaleString();

localeString = localeString.replace("/" , "年");

localeString = localeString.replace("/" , "月");

localeString = localeString.replace(" " , "日");

localeString = localeString.replace(":" , "点");

localeString = localeString.replace(":" , "分");

localeString = localeString + "秒";

console.log(localeString);

}

var date = new Date();

toCharacterString(date);// 2016年5月26日下午4点16分01秒

RegExp类型

ECMAScript通过RegExp类型来支持正则表达式。使用下面类似Perl的语法,就可以创建一个正则表达式。

var expression =/pattern/flags;

其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。每个正则表达式都可以有一或多个标志(flags),用以标明正则表达式的行为。正则表达式的匹配模式支持下列3个标志:

(1)g:表示全局(global)模式,即模式将被应用与所有字符串,而非在发现第一个匹配项时立即停止;

(2)i:表示不区分大小写模式(case-insensitive)模式,即在确定匹配时忽略模式与字符串的大小写;

(3)m:表示多行(nultiline)模式,即在到达一行文本末尾时还会继续查找系一行中是否存在与模式匹配的项。

因此,一个正则表达式就是一个模式与上述3个标志的组合体。不同组合产生不同结果,如:

/*

* 匹配字符串中所有“at”的实例

*/

var pattern1 = /at/g;

/*

* 匹配第一个“bat”或“cat”,不区分大小写

*/

var pattern2 = /[bc]at/i;

/*

* 匹配所有以“at”结尾的3个字符的组合,不分区大小写

*/

var pattern3 = /.at/gi;

与其他语言中的正则表达式类似,模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:

( [ { \ ^ $ | )? * +. ] }

这些元字符在正则表达式中都有一或多种特殊用途,因此想如果想要匹配字符串中包含的这些字符就必须对它们进行转义。如:

/*

* 匹配第一个“bat”或“cat”,不区分大小写

*/

var pattern1 = /[bc]at/i;

/*

* 匹配第一个“[bc]at”,不区分大小写

*/

var pattern2 = /\[bc\]at/i;

/*

* 匹配所有以“at”结尾的3个字符的组合,不分区大小写

*/

var pattern3 = /.at/gi;

/*

* 匹配所有以“.at”结尾的3个字符的组合,不分区大小写

*/

var pattern4 = /\.at/gi;

在上面的例子中,pattern1匹配第一个“bat”或“cat”,不区分大小写。而要想直接匹配“[bc]at”的话,就需要像定义pattern2一样,对其中的两个方括号进行转义。对于pattern3来说,句点表示位于“at”之前的让你一一个可以构成匹配项的字符。但如果想匹配”.at”,则必须对句点进行转义”\.”。

前面举的例子都是以字面量形式来定义的正则表达式。另一种创建正则表达式的方式是使用RegExp构造函数,它接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串。可以使用字面量定义的任何表达式,都可以使用构造函数来定义,如:

var pattern = new RegExp(“[bc]at” , “i”);

上面的语句等同于字面量形式的正则表达式:

var pattern = “/[bc]at/i”;

在使用构造函数时,传递的两个参数都是字符串(不能把正则表达式字面量传递给RegExp构造函数)。由于RegExp构造函数的模式参数是字符串,所以在某些情况下要对字符串进行双重转义。所有元字符都必须从双重转义,那些已经转义过的字符也是如此,例如\n(字符\在字符串中通常被转义为\\,而在正则表达式字符串中就会变成\\\\)。下表给出了一些模式,左边是这些模式的字面量形式,右边是使用RegExp构造函数定义相同模式时使用的字符串。

字面量模式

等价的字符串

/\[bc\]at/

“\\[bc\\]at”

/\.at/

“\\.at”

/name\/age/

“name\\/age”

/\d/\d{1,2}/

“\\d.\\d{1,2}”

/\w\\hello\\123/

“”\\w\\\\hello\\\\123

使用正则表达式字面量和使用RegExp构造函数的正则表达式不一样。在ECMAScript 3中,正则表达式字面量始终会共享同一个RegExp实例,而使用构造函数创建的每一个RegExp实例都是一个新实例。如:

var re = null,

i;

for(i=0;i<10;i++){

re=/cat/g;

re.test(“catastrophe”);

}

for(i=0;i<10;i++){

re=newRfgExp(“cat” , “g”);

re.test(“catastrophe”);

}

在第一个循环中,即使是循环体中指定的,但实际上只为/cat/创建了一个RegExp实例。由于实例属性不会重置,所以在循环中再次调用test()方法会失败。这是因为第一次调用test()找到了”cat”,但第二次调用是从索引为3的字符(上一次匹配的末尾)开始的,所以就找不到它了。由于会测试到字符串末尾,所以下一次再调用test()就又从头开始了。

第二个循环使用RegExp构造函数在每次循环中创建正则表达式。因为每次迭代都会创建一个新的RegExp实例,多疑每次调用test()都会返回true。

ECMAScript5明确规定,使用正则表达式字面量必须直接调用RegExp构造函数一样,每次都创建新的RegExp实例。IE9+、Firefox4+和Chrome都据此做出了修改。

RegExp实例属性

RegExp的每个实例都具有下列属性,通过这些属性可以取得有关模式的各种信息。

(1)global:布尔值,表示是否设置了g标志。

(2)ignoreCase:布尔值,表示是否设置了i标志。

(3)lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起。

(4)multiline:布尔值:表示是否设置了m标志。

(5)source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。

通过这些属性可以获知一个正则表达式的各方面信息,但却没有多大用处,因为这些信息全部包含在模式声明中。

RegExp实例方法

RegExp对象的主要方法是exec(),该方法是专门为捕获组而设计的。exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。返回的数组虽然是Array的实例,但包含两个额外的属性:index和Input。其中,index表示匹配项在字符串中的位置,而input表示应用正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)。如:

var text = "mom anddad and baby";

var pattern = /mom( and dad( and baby)?)?/gi;

var matches = pattern.exec(text);

alert(matches.index);//0

alert(matches.input);//mom and dad and baby

alert(matches[0]);//mom and dad and baby

alert(matches[1]);//and dad and baby

alert(matches[2]);//and baby

这个例子中的模式包含两个捕获组。最内部的捕获组匹配”and baby”,而包含它的捕获组匹配”and dad”或者”and dad and baby”。当把字符串传入exec()方法之后,发现了一个匹配项。因为整个字符串本身与模式匹配,所以返回的数组matches的index属性值为0。数组中的第一项是匹配的整个字符串,第二项包含与第一个捕获组匹配的内容,第三项包含与第二个捕获组匹配的内容。

对于exec()方法而言,即使在模式中设置了全局标志(g),它每次也只返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终返回第一个匹配项的信息。而在设置全局标志的情况下,每次调用exec()则都会在字符串中继续查找新匹配项,如:

var text = "cat,bat, sat, fat";

var pattern1 = /.at/;

var matches = pattern1.exec(text);

alert(matches.index);//0

alert(matches[0]);//cat

alert(pattern1.lastIndex);//0

var matches = pattern1.exec(text);

alert(matches.index);//0

alert(matches[0]);//cat

alert(pattern1.lastIndex);//0

var pattern2 = /.at/g;

var matches = pattern2.exec(text);

alert(matches.index);//0

alert(matches[0]);//cat

alert(pattern2.lastIndex);//3

var matches = pattern2.exec(text);

alert(matches.index);//5

alert(matches[0]);//bat

alert(pattern2.lastIndex);//8

这个例子中的第一个模式pattern1不是全局模式,因此每次调用exec()返回的都是第一个匹配项(“cat”)。而第二个模式pattern2是全局模式,因此每次调用exec()都会返回字符串中的下一个匹配项,直至搜索到字符串末尾为止。此外,还应该注意模式的lastIndex属性的变化情况。在全局模式匹配下,lastIndex的值在每次调用exec()后都会增加,而在非全局模式下则始终保持不变。

IE低版本的JavaScript实现在lastIndex属性上存在偏差,即使在非屈居模式下,lastIndex属性每次也会变化。但是在IE11环境下的测试结果如上面的测试代码,测试结果与Chrome、Firefox4中的测试结果是一致的不存在偏差。

正则表达式的第二个方法是test(),它接收一个字符串参数。在模式与该参数匹配的情况下返回true;否则,返回false。在只想知道目标字符串与某个模式是否匹配,但不要知道其文本内容的情况下,使用这个方法非常方便。因此,test()方法经常被用在if语句中,如:

var text = “000-00-0000”;

var pattern = /\d{3}-\d{2}-\d{4}/;

if(pattern.test(text)){

alert(“Thepattern was matched.”);

}

在这个例子中,使用正则表达式来测试了一个数字序列。如果输入的文本模式匹配,则显示一条消息。这种用法经常出现在验证用户输入的情况下,因为我们只想知道输入是不是有效,至于它为什么无效就无关紧要了。

RegExp实例继承的toLocaleString()和toString()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。例如:

var pattern = new RegExp(\\[bc\\]at , “gi”);

alert(pattern.toString());// /\[bc\]at/gi

alert(pattern.toLocaleString());// /\[bc\]at/gi

即使上例中的模式是通过调用RegExp构造函数创建的,toLocaleString()和toString()方法仍然会像它是以字面量形式创建的一样显示其字符串表示形式。

正则表达式的valueOf()方法返回正则表达式本身。

RegExp构造函数属性

RegExp构造函数包含一些属性(这些属性在其他语言中被看成是静态属性)。这些属性适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。关于这些属性的另一个独特之处,就是可以通过两种方式访问它们。换句话说,这些属性分别有一个长属性名和一个短属性名(Opera浏览器是例外,它不支持短属性名)。下表列出了RegExp构造函数的属性。

长属性名

短属性名

说明

input

$_

最近一次要匹配的字符串。Opera为实现此属性

lastMatch

$&

最近一次的匹配项。Opera为实现此属性

lastParen

$+

最近一次匹配的捕获组。Opera为实现此属性

leftContext

$`

input字符串中lastMatch之前的文本

multiline

$*

布尔值,表示是否所有表达式都使用多行模式。IE和Opera为实现此属性

rightContext

$’

input字符串中lastMatch之后的文本

使用这些属性可以从exec()或test()执行的操作中提取出更具体的信息。请看下面的例子:

var text = "This has been a short summer";

var pattern = /(.)hort/g;

/*

* 注意:Opera不支持input、lastMatch、lastParen和multiline属性

*Chrome、IE不支持multiline属性

*/

if(pattern.test(text)){

alert(RegExp.input);//This has been a short summer

alert(RegExp.leftContext);//This has been a

alert(RegExp.rightContext);//summer

alert(RegExp.lastMatch);//short

alert(RegExp.lastParen);//s

alert(RegExp.multiline);//(IE、Chrome)undefined;(Firefox)false

}

如前所述,例子使用的长属性名都可以用相应的短属性名来代替。只不过,由于这些短属性名大都不是有效的ECMAScript标识符,即带有特殊字符,因此必须通过方括号语法来访问它们,如:

var text = "This has been a short summer";

var pattern = /(.)hort/g;

/*

* 注意:Opera不支持input、lastMatch、lastParen和multiline属性

*Chrome、IE不支持multiline属性

*/

if(pattern.test(text)){

alert(RegExp.$_);//This has been a short summer

alert(RegExp["$`"]);//This has been a

alert(RegExp["$'"]);//summer

alert(RegExp["$&"]);//short

alert(RegExp["$+"]);//s

alert(RegExp["$*"]);//(IE、Chrome)undefined;(Firefox)false

}

除了上面介绍的几个属性之外,还有多达9个用于存储捕获数组的构造函数属性。访问这些属性的语法是RegExp.$1、RegExp.$2……RegExp.$9,分别用于存储第一、第二……第九个匹配的捕获数组。在调用exec()和test()方法时,这些属性会被自动填充。然后,就可以像下面这样使用它们:

var text = "This has been a short summer";

var pattern = /(..)or(.)/g;

if(pattern.test(text)){

alert(RegExp.$1);//sh

alert(RegExp.$2);//t

}

这里创建了一个包含两个捕获组的模式,并用该模式检测了一个字符串。即使test()方法只返回一个布尔值,但RegExp构造函数的属性$1和$2也会被匹配相应捕获组的字符串自动填充。

模式的局限性

尽管ECMAScript中的正则表达式功能还是比较完备的,但仍然缺少某些语言(特别是Perl)所支持的高级正则表达式特性。下面列出了ECMAScript正则表达式不支持的特性:

(1)匹配字符串开始和结尾的\A和\Z锚

(2)向后查找

(3)并集和交集类

(4)原子组

(5)Unicode支持(单个字符除外,如\uFFFF)

(6)命名的捕获组

(7)s(single , 单行)和x(free-spacing, 无间隔)匹配模式

(8)条件匹配

(9)正则表达式注释

即使存在这些限制,ECMAScript正则表达式仍然是非常强大的,能够帮我们绝大多数模式匹配任务。

元字符

元字符(Meta Character)是能够匹配一个位置或某个字符串的一个字符。元字符分为两类:匹配位置的元字符和匹配字符的元字符。

匹配位置的元字符及作用如下表:

字符

作用

^

指示从行的开始位置进行匹配

$

指示从行的结束位置开始匹配

\b

匹配单词的开始或结束位置

匹配字符的元字符有7个,作用如下:

字符

作用

.

匹配除换行符以外的任意字符

\w

匹配单字字符(a~z,A~Z,0~9及下画线)

\W

匹配非单字字符

\s

匹配空白字符(如空格、制表符、换行符等)

\S

匹配非空字符

\d

匹配数字字符(0~9)

\D

匹配非数字字符

字符类

元字符只能匹配一个位置或字符合集中的一个字符,如果要匹配字符集合(如[0,1,2,3,4])时,则需要定义匹配的字符集合。字符类就是括号中的一个字符集,只匹配括号内的任意字符。

下述正则表达式匹配HTML文本中的

在使用字符类进行匹配时,对于连续的字符(如:a~z A~Z,0~9等),如果全在括号中列举很不方便,此时可以使用范围符“-”来定义字符的范围,如上面正则表达式等同于

而对于8位的电话号码可以定义为:\b[0-9]0-9[0-9][0-9][0-9][0-9][0-9]0-9[0-9][0-9]\b

转义字符

对于诸如“^”“$”这样的字符都有特殊意义,如果需要在正则表达式中匹配字符串中的“^”“&”等字符时,则需要使用转义字符“\”(反斜杠)来解决这一问题。

如:www\.baidu\.com可以匹配www.baidu.com

限定符

一个元字符只能匹配一个字符,如果需要匹配零个、一个或多个字符时,可以使用限定符。限定服用于指定允许特定字符或字符集自身重复出现的次数。有*,+,?,{n},{n,}和{n,m}共6种

限定符

作用

示例

*

匹配前面的子表达式零次或多次

如:zo*能匹配“z”“zoo”*等价于{0,}

+

匹配前面的子表达式一次或多次

如:zo+能匹配”zo”及”zoo”但不能匹配”z” +等价于{1,}

?

匹配前面的子表达式零次或一次

如:do[es]?能匹配“do”或“does”中的”doe”,?等价于{0,1}

{n}

匹配确定的n次,n是一个非负整数

如:o{2}能匹配“food”中的两个“oo”

{n,}

至少匹配n次,n是一个非负整数

如:o{2}能匹配“fooood”中的所有”o”,但不能匹配“Tom”中的”o”o{1,}等价于o+

{n,m}

至少匹配n次,至多匹配m次,n和m是一个非负整数,其中n<=m

如:o{1,3}将匹配“fooood”中的前三个“o”。o{0,1}等价于o?

引入限定符后对于8位的电话号码可以定义为:\bd{8}\b

下述正则表达式限制数字型字符串的整数位最多为3位,小数位为两位:^d{0,3}\.\d{2}\b

如果在限定符之后再添加一个字符“?”,则表示尽可能少的重复字符“?”之前的限定符号重复次数,此种匹配方式称为懒惰匹配。如果不加“?”则默认为贪婪匹配,即匹配最长的字符串。

以下正则表达式匹配以字母a开头以字母b结尾的最长字符串:a.*b;

以下正则表达式匹配以a开头以b结尾的最长的字符串:a.*?b;

反义

在使用正则表达式时,如果需要匹配不在字符集指定范围内的字符时,可以使用反义字符“^”(脱字符)进行声明。

分组

“(” “)”。下述表达式可以匹配IP(IPv4)地址:(\d{1,3}\.){3}\d{1,3}

相关TAG标签
上一篇:Binder机制——初探
下一篇:bzoj1853【SCOI2010】幸运数字
相关文章
热门专题推荐 vmware win7激活工具 win10激活工具 excel word office激活 小马激活工具 重装系统 数据恢复 u盘启动工具
图文推荐
文章
推荐
热门新闻

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站